Neste artigo criaremos um aplicação simples utilizando Spring MVC juntamente com MongoDB.
Boa Leitura.
Antes de começarmos a criar nosso projeto, primeiramente tem que conhecer um pouco sobre o banco de dados mongodb e Mongo Shell. Sua instalação pode ser vista aqui Obtendo e Configurando o MongoDB em seu Ambiente.
Spring MVC é um framework Action Based que tem ganhado bastante espaço ultimamente no universo Java para criação de projeto Web, antes dele era Struts 1 que também é um framework Action Based.
O projeto vai ser bem simples, um crud utilizando mongodb com um relacionamento entre dois documentos.
Criando o Projeto
Com o Eclipse aberto, vá File -> New – > Maven Project irá abrir a seguinte Janela :
clique em Next para ir para a seguinte tela :
clique em Next, na próxima deixe preenchida da seguinte forma e clique em Finish:
com o projeto criado,vá em src/main/webapp, nela apague a pasta WEB-INF. Depois clique com o botão direito do mouse e vá em Properties, navegue até a opção Targeted Runtimes, marque a opção, que no caso vamos utilizar o Tomcat, depois clique em Uninstall Facets… :
ao chegar nesta tela desmaque Dynamic Web Module , altere Java 1.5 para 1.8 e clique em Finish. Abra novamente a mesma tela e maque Dynamic Web Module e mude de 2.3 para 3.1 e clique em Next para configura a proxima tela e a configure como abaixo :
Clique em Finish e depois em OK.
Agora iremos configurar nosso pom.xml, com a seguinte configurações :
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>br.com.danieldias</groupId> <artifactId>SpringMongo</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringMongo Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!-- Mongo Driver --> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver</artifactId> <version>3.2.2</version> </dependency> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.0.RELEASE</version> </dependency> <!-- JSTL --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> </dependencies> <build> <finalName>SpringMongo</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> </project>
Na pasta WEB-INF , configure o web.xml na seguinte forma :
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>SpringMongo</display-name> <servlet> <servlet-name>springDispatcherServlet</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>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
Ainda dentro de WEB-INF crie um xml com o nome spring-context.xml, com o seguinte conteúdo e também crie uma pasta chamada views:
<?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/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd"> <!-- scaneia todos os pacotes a procura de componentes do Spring--> <context:component-scan base-package="br.com.danieldias"/> <context:annotation-config /> <mvc:annotation-driven /> <!-- configura css,js,etc --> <mvc:resources location="/recursos/" mapping="/recursos/**"/> <!-- Configurando a localização das Views. --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
Agora na pasta webapp crie uma pasta chamada recursos com as seguinte subpastas : css, js e imagens, dentro de cada uma delas seguinte arquivos :
- jquery-ui-1.9.2.custom.min.css
- calendar.gif
- datepicker-pt-BR.js
- jquery-3.1.0.min.js
- jquery-ui-1.9.2.custom.min.js
Depois clique em cima do projeto e de “Alt +F5” para fazer update do maven :
Clique em OK e finalizamos a parte de criação projeto, podemos da inicio a codificação de nossas classes .
Criando a Constantes.java
Está classe é bem simples, ela irá somente conter valores constantes, que não serão modificadas. Isso para evitar ter muitas hardCode espalhado por todo o código, assim esse classe irá centralizar tudo de maneira organizada.
Crie uma classe chamada Constantes no package br.com.danieldias.commons, com o seguinte conteúdo :
package br.com.danieldias.commons; /** * @author daniel * github:Daniel-Dos * daniel.dias.analistati@gmail.com * twitter:@danieldiasjava */ public class Constantes { /*Nome o Banco e da Collection*/ public static final String BANCO_NOME = "danieldiasjava"; public static final String COLLECTION_NOME = "pessoas"; /*Nomes das Colunas para o MongoDB*/ public static final String NOME = "nome"; public static final String IDADE = "idade"; public static final String PROFISSAO = "profissao"; public static final String ENDERECO = "endereco"; public static final String CIDADE = "cidade"; public static final String BAIRRO = "bairro"; public static final String ESTADO = "estado"; public static final String NASCIMENTO = "nascimento"; public static final String JUGS = "jugs"; }
Criando as Entidades
Crie as classes Pessoa.java e Endereco.java no package br.com.danieldias.model , com o seguinte conteúdo :
package br.com.danieldias.model; import java.util.Calendar; import org.springframework.format.annotation.DateTimeFormat; /** * @author daniel * github:Daniel-Dos * daniel.dias.analistati@gmail.com * twitter:@danieldiasjava */ public class Pessoa { private String nome; private String profissao; private String jugs; private int idade; private Endereco endereco; @DateTimeFormat(pattern="dd/MM/yyyy") private Calendar dataNascimento; public Pessoa() { this("","","",0,null,null); } public Pessoa(String nome, String profissao, String jugs, int idade, Endereco endereco,Calendar dataNascimento) { this.nome = nome; this.profissao = profissao; this.jugs = jugs; this.idade = idade; this.endereco = endereco; this.dataNascimento = dataNascimento; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getProfissao() { return profissao; } public void setProfissao(String profissao) { this.profissao = profissao; } public String getJugs() { return jugs; } public void setJugs(String jugs) { this.jugs = jugs; } public int getIdade() { return idade; } public void setIdade(int idade) { this.idade = idade; } public Endereco getEndereco() { return endereco; } public void setEndereco(Endereco endereco) { this.endereco = endereco; } public Calendar getDataNascimento() { return dataNascimento; } public void setDataNascimento(Calendar dataNascimento) { this.dataNascimento = dataNascimento; } }
A classe pessoa bem simples, apenas com uma anotação na dataNascimento para o Spring lidar com esse tipo.
package br.com.danieldias.model; /** * @author daniel * github:Daniel-Dos * daniel.dias.analistati@gmail.com * twitter:@danieldiasjava */ public class Endereco { private String cidade; private String bairro; private String estado; public Endereco() { this("","",""); } public Endereco(String cidade, String bairro, String estado) { this.setCidade(cidade); this.setBairro(bairro); this.setEstado(estado); } public String getCidade() { return cidade; } public void setCidade(String cidade) { this.cidade = cidade; } public String getBairro() { return bairro; } public void setBairro(String bairro) { this.bairro = bairro; } public String getEstado() { return estado; } public void setEstado(String estado) { this.estado = estado; } }
Criando o Repositorio
Agora criaremos uma Inteface chamada MongoDAO e uma classe chamada PessoaDAO no package br.com.danieldias.persistencia, com os seguintes conteúdos:
package br.com.danieldias.persistencia; import org.bson.Document; import com.mongodb.client.MongoCursor; import br.com.danieldias.model.Pessoa; /** * @author daniel * github:Daniel-Dos * daniel.dias.analistati@gmail.com * twitter:@danieldiasjava */ public interface MongoDAO { void inserir(Pessoa pessoa); void atualizar(Pessoa pessoa); void excluir(Object _id); Document porId(Object _id); MongoCursor<Document>mostraTodos(); }
A classe PessoaDAO é onde fica todas as operações de CRUD para o MongoDB, nada muito fora do comum, tudo muito simples e fácil compreensão. Repare que estamos usando a classe Constantes aqui no lugar de String para facilitar o entendimento e deixar o código mas limpo.
package br.com.danieldias.persistencia; import static com.mongodb.client.model.Filters.eq; import java.util.ArrayList; import java.util.List; import org.bson.Document; import org.springframework.stereotype.Repository; import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; import br.com.danieldias.commons.Constantes; import br.com.danieldias.model.Pessoa; /** * @author daniel * github:Daniel-Dos * daniel.dias.analistati@gmail.com * twitter:@danieldiasjava */ @Repository public class PessoaDAO implements MongoDAO { MongoClient conexao; MongoDatabase dataBase; MongoCollection<Document> collectionPessoas; public PessoaDAO() { conexao = new MongoClient(); dataBase = conexao.getDatabase(Constantes.BANCO_NOME); collectionPessoas = dataBase.getCollection(Constantes.COLLECTION_NOME); } @Override public void inserir(Pessoa pessoa) { List<Document> jugs = new ArrayList<>(); jugs.add(new Document(Constantes.NOME,pessoa.getJugs())); collectionPessoas.insertOne( new Document(Constantes.NOME,pessoa.getNome()) .append(Constantes.IDADE, pessoa.getIdade()) .append(Constantes.PROFISSAO, pessoa.getProfissao()) .append(Constantes.ENDERECO, new Document(Constantes.CIDADE,pessoa.getEndereco().getCidade()) .append(Constantes.BAIRRO, pessoa.getEndereco().getBairro()) .append(Constantes.ESTADO, pessoa.getEndereco().getEstado()) ) .append(Constantes.NASCIMENTO, pessoa.getDataNascimento().getTime()) .append(Constantes.JUGS,jugs) ); } @Override public void atualizar(Pessoa pessoa) { collectionPessoas.updateOne(eq(Constantes.NOME,pessoa.getNome()), new Document("$set", new Document(Constantes.IDADE,pessoa.getIdade()) .append(Constantes.PROFISSAO, pessoa.getProfissao()) .append(Constantes.ENDERECO, new Document(Constantes.CIDADE,pessoa.getEndereco().getCidade()) .append(Constantes.BAIRRO, pessoa.getEndereco().getBairro()) .append(Constantes.ESTADO, pessoa.getEndereco().getEstado()) ) ) ); } @Override public void excluir(Object _id) { collectionPessoas.deleteOne(porId(_id)); } @Override public Document porId(Object _id) { return collectionPessoas.find(eq("_id",_id)).first(); } @Override public MongoCursor<Document> mostraTodos() { return collectionPessoas.find().iterator(); } }
Criando os Controles
O primeiro controle que iremos criar ,será o que chama a pagina principal listando todos os dados do banco quando iniciar a aplicação.
Crie uma nova classe chamada IndexController no package br.com.danieldias.controller, com o seguinte conteúdo :
package br.com.danieldias.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author daniel * github:Daniel-Dos * daniel.dias.analistati@gmail.com * twitter:@danieldiasjava */ @Controller @RequestMapping("*") public class IndexController { @RequestMapping("*") public String index() { return "redirect:/pessoas/listaPessoa"; } }
Ainda no mesmo package cria a classe PessoasControler com o seguinte conteúdo :
package br.com.danieldias.controller; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import br.com.danieldias.model.Pessoa; import br.com.danieldias.persistencia.MongoDAO; /** * @author daniel * github:Daniel-Dos * daniel.dias.analistati@gmail.com * twitter:@danieldiasjava */ @Controller @RequestMapping("/pessoas") public class PessoasControler { @Autowired MongoDAO dao; @GetMapping("/inserirPessoa.html") public ModelAndView cadastrar() { return new ModelAndView("inserirPessoa"); } @GetMapping("/alterarPessoa.html/{_id}") public ModelAndView alterar(@PathVariable("_id") ObjectId _id) { return new ModelAndView("alterarPessoa","atualizar",dao.porId(_id)); } @PostMapping("inserirPessoa") public String adicionar(Pessoa pessoa) { dao.inserir(pessoa); return "redirect:/pessoas/listaPessoa"; } @GetMapping("listaPessoa") public String listar(Model model) { model.addAttribute("listas", dao.mostraTodos()); return "lista"; } @PostMapping("alterar") public String update(Pessoa pessoa) { dao.atualizar(pessoa); return "redirect:/pessoas/listaPessoa"; } @GetMapping("remover/{_id}") public String deletar(@PathVariable("_id") ObjectId _id) { dao.excluir(_id); return "redirect:/pessoas/listaPessoa"; } }
Está classe também tem um conteúdo bem simples, a única diferença são as novas anotações para Mapping que a partir do Spring 4.3.0 , podemos está utilizando essas anotações : @GetMapping, @PostMapping, que são a mesma coisa quando fazemos desta maneira : @RequestMapping(value = “alterar”, method = “RequestMethod.POST”)
Criando as Views
Agora daremos inicio a criação de 3 páginas para nossa aplicação que são : alterarPessoa.jsp, inserirPessoa.jsp e lista.jsp, que devem ser criada na pasta views que fica dentro de WEB-INF .
Iniciaremos pela a página lista.jsp, onde a mesma terá uma tabela onde os dados serão apresentados, 3 links um para chamar a paǵina alterarPessoa.jsp passando um parâmetro que é seu id e um que irá chamar no controle o deletar com parâmetro id e um para estarmos adicionando os dados no formulario inserirPessoa.jsp
A página fica da seguinte forma :
<%@ 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://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Lista de Pessoas</title> </head> <body> <h1 align="center">Listagem dos Dados</h1> <a href="inserirPessoa.html">Adicionar</a> <table align="center" border="4"> <tr bgcolor="gray"> <th>ID</th> <th>Nome</th> <th>Idade</th> <th>Profissão</th> <th>Cidade</th> <th>Bairro</th> <th>Estado</th> <th>Jugs</th> <th>Data</th> <th>Editar</th> <th>Deletar</th> </tr> <c:forEach items="${listas}" var="pessoas"> <tr> <td>${pessoas._id}</td> <td>${pessoas.nome}</td> <td>${pessoas.idade}</td> <td>${pessoas.profissao}</td> <td>${pessoas.endereco.cidade}</td> <td>${pessoas.endereco.bairro}</td> <td>${pessoas.endereco.estado}</td> <td>${pessoas.jugs.get(0).nome}</td> <td> <fmt:formatDate value="${pessoas.nascimento}" pattern="dd/MM/yyyy"/> </td> <td><a href="alterarPessoa.html/${pessoas._id }">Alterar</a></td> <td><a href="remover/${pessoas._id}">Excluir</a></td> </tr> </c:forEach> </table> </body> </html>
Algo importante nesta tela. Aqui os atributos passado devem SER o mesmo que estão no mongoDB, ou seja as colunas tem que ter os mesmo nome. A mesma coisa nesse techo : ${pessoas.jugs.get(0).nome}, aqui estou retornado o primeiro posição no array, se quisermos chamar outra posição fazemos assim : ${pessoas.jugs.get(1).lideres}.
A proxima tela é um formulario bem simples com o seguinte conteudo :
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Inserir Pessoas</title> <link rel="stylesheet" href="../recursos/css/jquery-ui-1.9.2.custom.min.css"> <script src="../recursos/js/jquery-3.1.0.min.js"></script> <script src="../recursos/js/jquery-ui-1.9.2.custom.min.js"></script> <script src="../recursos/js/datepicker-pt-BR.js"></script> <script type="text/javascript"> $(function(){ $("#date").datepicker({ showOn:"button", buttonImage:"../recursos/imagem/calendar.gif", buttonImageOnly:true }); }); </script> </head> <body> <form action="inserirPessoa" method="post"> <fieldset> <legend>Dados</legend> Nome: <input type="text" name="nome" /> Idade: <input type="number" name="idade"/> Profissão: <input type="text" name="profissao"/> Cidade: <input type="text" name="endereco.cidade"/> Bairro: <input type="text" name="endereco.bairro"/> Estado: <input type="text" name="endereco.estado"/> Data de Nascimento: <input id="date" type="text" name="dataNascimento" placeholder="dd/mm/yyyy"/> JUGS: <input type="checkbox" name="jugs" value="SouJava"/>SouJava <input type="checkbox" name="jugs" value="RioJug"/>RioJug <input type="checkbox" name="jugs" value="SouJava Campinas"/>SouJava Campinas <input type="submit" value="Cadastrar Dados."/></fieldset> </form> </body> </html>
e última tela que contem um formulário já preenchido com os valores do banco que podem ser alterados :
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Alterar Pessoas</title> </head> <body> <form action="../alterar" method="post"> <fieldset> <legend>Alteração de Dados</legend> Nome: <input type="text" name="nome" value="${atualizar.nome}" disabled="disabled"/> Idade: <input type="number" name="idade" value="${atualizar.idade}"/> Profissão: <input type="text" name="profissao" value="${atualizar.profissao}"/> Cidade: <input type="text" name="endereco.cidade" value="${atualizar.endereco.cidade}"/> Bairro: <input type="text" name="endereco.bairro" value="${atualizar.endereco.bairro}"/> Estado: <input type="text" name="endereco.estado" value="${atualizar.endereco.estado}"/> <input type="submit" value="Alterar Dados."/></fieldset> </form> </body> </html>
Rodando a Aplicação
Com tudo pronto, podemos testar a nossa aplicação:
Primeiramente inicie o MongoDB através do prompt/terminal com o seguinte comando : mongod, como na imagem :
Depois rode a aplicação no tomcat , com o botão direito do mouse clique no seu projeto e vá em Run As -> Run on Server, ao inicia a aplicação a página principal será carregada com abaixo :
Ao clicar em Adicionar irá para a tela de cadastro :
Ao clicar em adicionar, a pagina irá redirecionar para a tela principal novamente com os dados carregados :
Ao clicar no link Alterar, vai carregar a pagina de alteração de dados e se clicar em Excluir vai apagar o dado e vai voltar para a pagina principal :
RoboMongo
Com os nossos dados Gravados, podemos ver como fica a sua estrutura no banco, ao invés de utilizar o mongo Shell para visualizar os dados , irei usar uma ferramente de administraçao para está lidando com varias operações referente ao MongoDB, essa ferramente se chama RoboMongo , instalação facil basta descompactar e executar .
Ao executar o RoboMongo irá aparecer a seguinte tela :
clique em Create , de um nome para a conexao e clique em OK :
depois de salvo, clique em Connect, que irar leva-lo a seguinte pagina,basta clicar na collection pessoas e ira carregar os dados armazenados :
Bem isso é tudo, aqui aprendemos a como fazer uma aplicação Spring MVC com MongoDB e de quebra conhecemos uma nova ferramenta para o mesmo. O projeto pode ser baixado no meu GitHub.
REFERÊNCIAS
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/