Spring Novo PDF - Thymeleaf, Java e MVC - Prof. Pedro Clarindo da Silva Neto
Document Details

Uploaded by SelfSufficientQuasar
Prof. Pedro Clarindo da Silva Neto
Tags
Summary
Este documento PDF, de autoria do Prof. Pedro Clarindo da Silva Neto, explora o uso do Thymeleaf, uma template engine para Java, em conjunto com o Spring MVC. O conteúdo aborda desde a exibição de mensagens até a criação de modelos HTML dinâmicos, essencial para o desenvolvimento web moderno com Java. A utilização de exemplos e boas práticas ajudam o leitor a compreender e aplicar os conceitos aprendidos.
Full Transcript
Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Vamos colocar a mensagem que irá aparecer para o usuário, para isso vamos usar um alert do Bootstrap, no arquivo de Cadastro. DICA: Relembra...
Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Vamos colocar a mensagem que irá aparecer para o usuário, para isso vamos usar um alert do Bootstrap, no arquivo de Cadastro. DICA: Relembrar um pouco de Bootstrap Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Agora vamos configurar para que essa div seja exibida apenas quando houver uma mensagem a ser mostrada. Utilizaremos para isso o Thymeleaf. Primeiramente iremos colocar o namespace do Thymeleaf dentro da tag HTML. Utilizaremos o prefixo th em nossa aplicação Prof. Pedro Clarindo da Silva Neto Thymeleaf - uma template engine A view irá retornar apenas um HTML para o browser do cliente, mas isso deixa uma dúvida: Como ela recebe os objetos Java, enviados pelo controller, e os transforma em HTML? Nessa hora que entra em ação o Thymeleaf! Teremos um código HTML misturado com alguns atributos do Thymeleaf, que após processado, será gerado apenas o HTML para ser renderizado no browser do cliente. Prof. Pedro Clarindo da Silva Neto Thymeleaf - uma template engine O Thymeleaf é um template engine para Java e uma alternativa ao JSP. Os templates são escritos, em sua maioria, com código HTML5 e tem boa integração com o Spring Framework, além da capacidade de processar código CSS e JavaScript. O principal objetivo do Thymeleaf é trazer modelos naturais elegantes para o seu fluxo de trabalho de desenvolvimento - HTML que pode ser exibido corretamente nos navegadores e também funciona como protótipos estáticos, permitindo uma colaboração mais forte nas equipes de desenvolvimento. Prof. Pedro Clarindo da Silva Neto Thymeleaf - uma template engine O Thymeleaf não é um projeto Spring, mas uma biblioteca que foi criada para facilitar a criação da camada de view, com uma forte integração com o Spring, e uma boa alternativa ao JSP. O principal objetivo do Thymeleaf é prover uma forma elegante e bem formatada para criarmos nossas páginas. O dialeto do Thymeleaf é bem poderoso. Prof. Pedro Clarindo da Silva Neto Thymeleaf - uma template engine Os modelos HTML escritos no Thymeleaf ainda parecem e funcionam como HTML, permitindo que os modelos reais executados em seu aplicativo continuem funcionando como artefatos de design úteis. Prof. Pedro Clarindo da Silva Neto Thymeleaf - uma template engine Para você ver como ele funciona, vamos analisar o código abaixo. A expressão ${} interpreta variáveis locais ou disponibilizadas pelo controller. O atributo th:each itera sobre a lista convidados, atribuindo cada objeto na variável local convidado. Isso faz com que vários elementos tr sejam renderizados na página. Dentro de cada tr existem 2 elementos td. O texto que eles irão exibir vem do atributo th:text, junto com a expressão ${}, lendo as propriedades da variável local convidado. Prof. Pedro Clarindo da Silva Neto Thymeleaf - uma template engine Ótima documentação: https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html Fazer a leitura. Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Iremos utilizar uma condicional dentro do Thymelaf, o th:if, IF que é uma estrutura já conhecida de outras linguagens, que tem como retorno um booleano e que recebe alguma condição para comparar. Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Iremos utilizar uma condicional dentro do Thymelaf, o th:if, IF que é uma estrutura já conhecida de outras linguagens, que tem como retorno um booleano e que recebe alguma condição para comparar. Expressão do thymeleaf, aparece entre ${ } #strings - objeto utilitário para trabalhar com strings Como temos o sinal Uso do th: if !, então irá retornar do isEmpty - se for Vazio TRUE se NÃO thymeleaf estiver vazio Mensagem - uma variável que será passada como parâmetro Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Execute agora e veja que o alert irá desaparecer: Como o atributo mensagem está vazio, o alert não aparece Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Criando a mensagem no Controller: Antes Depois Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Ao invés de devolver uma String, devolveremos um ModelAndView. Essa classe foi utilizada para especificar a view que será renderizada para o usuário final e para informarmos quais os dados ela utilizará para isso. View que será renderizada Dados que serão utilizados, nesse caso um objeto chamado mensagem que tem como conteúdo "Foi salvo com sucesso!" Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Testando... Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Contudo, a mensagem criado no controller era: "Foi salvo com sucesso!" Mas foi essa mensagem que apareceu. Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Ainda está pegando a mensagem do HTML Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Para resolver isso, vamos recorrer novamente ao Thymeleaf, usando o atributo th:text, que avalia sua expressão e define o resultado dessa avaliação como o corpo da tag em que está, neste caso, na tag span. Prof. Pedro Clarindo da Silva Neto Mostrando mensagem para o usuário Agora sim! HTML gerado Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Atualmente, o campo de status está de forma estática, estamos escrevendo os valores direto no HTML. Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Neste caso, precisamos receber um coleção dos status, iterar sobre ele e devolver ao usuário. Assim como fizemos com a mensagem, primeiramente precisamos alterar no Controller. Antes Depois Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Neste caso, precisamos receber um coleção dos status, iterar sobre ele e devolver ao usuário. Assim como fizemos com a mensagem, primeiramente precisamos alterar no Controller. Aqui irá retornar todos os StatusTitulo Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica No HTML de Cadastro, utilizaremos o th:each para iterar sobre os Status que foram passados pelo Controller. Aqui irá retornar todos os StatusTitulo Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica O valor do atributo status : ${todosStatusTitulo} significa $ {todosStatusTitulo}, repita esse fragmento de modelo configurando esse elemento em uma variável chamada status. Expressão iterada Variável de iteração Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Lembrando um pouco o Enum StatusTitulo descrição Status Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Colocará a descrição do Status correspondente, que ficará visível ao Irá colocar no usuário, Recebido ou parâmetro VALUE, o Pendente status, RECEBIDO ou PENDENTE Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica O HTML resultante será: th:value th:text Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Não apenas os objetos java.util.List podem ser usados para iteração no Thymeleaf. De fato, existe um conjunto bastante completo de objetos que são considerados iteráveis por um atributo th: each: Qualquer objeto implementando java.util.Iterable Qualquer objeto que implementa java.util.Map. Ao iterar mapas, as variáveis do iter serão da classe java.util.Map.Entry. Qualquer array Qualquer outro objeto será tratado como se fosse uma lista de valor único contendo o próprio objeto. Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Vamos testar agora e ver se funciona... Ok, está salvo no banco. Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Contudo, quando retorna a mensagem para o usuário, o status desaparece. Sumiu! Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Isso acontece, pois passamos os Status Titulo dentro do mapeamento /novo Após, clicar no botão de enviar, o mapeamento muda. Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Podemos resolver isso utilizando um ModelAttribute no Controller. ModelAttribute é uma anotação que liga um parâmetro de método ou valor de retorno de método a um atributo de modelo nomeado, exposto a uma visualização da web. Neste caso, o atributo ficará disponível para todas as páginas. É preciso retirar o addObjetct, que foi adicionado ao mapeamento /novo Prof. Pedro Clarindo da Silva Neto Populando campos de forma dinâmica Agora sim, usando ModelAttibute, os Status ficam disponíveis tando /titulos/novo, quanto para /titulos Prof. Pedro Clarindo da Silva Neto Utilizando o MySQL no projeto Primeiramente será necessário retirar a dependência do H2 e colocar a do MySQL Connector no pom.xml Prof. Pedro Clarindo da Silva Neto Utilizando o MySQL no projeto Precisamos colocar algumas informações no arquivo application.properties, nele são informadas as propriedades para serem utilizadas na nossa aplicação. Prof. Pedro Clarindo da Silva Neto Utilizando o MySQL no projeto Repassando os dados do banco no arquivo application.properties: É preciso criar o banco de dados cobrancas no MySQL Prof. Pedro Clarindo da Silva Neto Utilizando o MySQL no projeto Vamos fazer o teste: Prof. Pedro Clarindo da Silva Neto Utilizando o MySQL no projeto Deu um erro! Prof. Pedro Clarindo da Silva Neto Utilizando o MySQL no projeto A tabela titulo não existe. Neste caso precisamos informar no application.properties que o Hibernate/JPA ficará responsável por isso. Fazer a leitura do Common Application properties: https://docs.spring.io/spring-boot/docs/ current/reference/html/appendix-applic ation-properties.html#data-properties Prof. Pedro Clarindo da Silva Neto Utilizando o MySQL no projeto Agora sim, deu certo. Visualização no MySQL Workbench Prof. Pedro Clarindo da Silva Neto Criando a página de pesquisa Criar em Templates, o arquivo PesquisaTitulos.html Prof. Pedro Clarindo da Silva Neto Criando a página de pesquisa Colocar a estrutura padrão no arquivo PesquisaTitulos.html Prof. Pedro Clarindo da Silva Neto Criando a página de pesquisa Criaremos uma tabela que irá receber os dados do banco: Id, Descrição, Data de vencimento, Valor, Status, além de mais uma coluna que irá guardar os espaços dos botões para alterar e excluir. Prof. Pedro Clarindo da Silva Neto Criando a página de pesquisa Para que possamos ver a página, precisamos mapea-la no Controller. Prof. Pedro Clarindo da Silva Neto Criando a página de pesquisa Na anotação RequestMapping não foi passado nenhum outro valor como nos métodos novo() e salvar(). Neste caso, em pesquisar() será atribuída o mesmo mapeamento realizado no início do controller. Prof. Pedro Clarindo da Silva Neto Criando a página de pesquisa Agora quando acessar localhost:8080/titulos, a página acessada será essa: Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Se observarmos, nossas páginas tem muitos itens semelhantes, o que pode fazer o programador escrever muito código repetido. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Podemos então transformar boa parte disso em um layout. Para nos auxiliar vamos utilizar uma ferramenta chamada Thymeleaf Layout Dialect (https://github.com/ultraq/thymeleaf-layout-dialect). Com ele, iremos criar um layout padrão para o sistema e preencher com as informações específicas de cada página. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Vamos adicionar a dependência no pom.xml Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Criar dentro de templates, o arquivo LayoutPadrao.html Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf No arquivo LayoutPadrao.html, colocar o seguinte código: Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Perceba que o código utilizado é o mesmo do arquivo PesquisaTitulos.html, mas sem o conteúdo central. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Vamos retirar o conteúdo do PesquisaTitulos.html que foi repassado para o LayoutPadrao.html Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Novo PesquisaTitulos Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Dentro de LayoutPadrao.html vamos incluir o namespace do Thymeleaf Layout Dialect. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Agora vamos inserir em nosso layout (LayoutPadrao.html), um local que será preenchido pelo conteúdo das páginas. Insira logo abaixo do código da barra de navegação Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Como minhas páginas vão saber que existe o Layout? Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf No arquivo PesquisaTitulos.html, vamos colocar também o namespace do Thymeleaf Layout Dialect e adicionar também que será o decorator, passando nosso Layout como valor. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Vamos inserir no código de PesquisaTitulos.html também uma section para informar ao layout quem é o conteúdo. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Observe que essa section de PesquisaTitulos.html recebe o valor layout:fragment="conteudo" Idêntico ao que inserimos no nosso LayoutPadrao.html Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Verifique se depois de modificar a página PesquisaTitulos com o uso de Layout ela ainda continua funcionando como antes. Vamos testar? Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf TAREFA Fazer o mesmo procedimento com a página de Cadastro. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Olhando nossas páginas, é possível observar que a repetição de código diminuiu, graças ao Layout. Uma outra recurso que podemos utilizar com o Layout é poder separar alguns itens de layout para podermos administrá-lo melhor. Neste caso, faremos isso com a barra de navegação que está gerando o cabeçalho das nossas páginas. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Dentro da pasta templates, crie o arquivo Cabecalho.html. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Dentro de Cabecalho.html, colocar o seguinte código: Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf A parte destacada foi retirada de LayoutPadrao.html. Desta forma, se eu tiver que implementar somente meu cabeçalho, temos um arquivo exclusivo. Prof. Pedro Clarindo da Silva Neto Templates com Thymeleaf Para que o cabeçalho seja incluído dentro do Layout novamente, utilizaremos o th:replace no nosso código: O LayoutPadrao.html ficará assim Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Vamos enviar os dados do controller para a view na página de pesquisa (PesquisaTitulos.html). Inicialmente vamos na classe TitulosController e implementar uma forma de enviar esses titulos. Iremos utilizar a interface Titulos que foi injetada (@Autowired) pelo Spring IOC para nos prover os recursos que precisaremos. Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Dentro do método pesquisar, vamos obter todos os títulos utilizando o findAll(), já disponibilizado pelo JpaRepository. Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Agora o pesquisar precisará retornar além da view, também os títulos. Por isso o pesquisa terá como retorno um ModelAndView, como já tínhamos feito antes. Utilizaremos esse nome na nossa view Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Da mesma forma que fizemos na página de cadastro, onde listamos os status do titulos, utilizaremos o th:each para gerar os titulos cadastrados. Insira esse código no PesquisaTitulos.html Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Agora nossa página de pesquisa de títulos está assim: Precisamos retirar essa mensagem, já que temos registros em exibição. Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Atualmente ele está estático. Para resolver isso utilizaremos um objeto utilitário do Thymeleaf, o #lists. O código ficará assim: Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Nesta condição criada pelo th:if, dizemos que a mensagem só será exibida caso a lista de títulos esteja vazia. Dê uma olhada na documentação: https://www.thymeleaf.org/apidocs/thymeleaf/3.0.0.RELEA SE/index.html?org/thymeleaf/expression/Lists.html Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Agora sim, mensagem apagada. Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Precisamos melhorar a aparência da data de vencimento e a do valor, o formato não está agradável. Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Para isso, vamos incluir mais um conjunto de chaves nos elementos de data e valor, que o Thymeleaf irá buscar os padrões definidos no modelo de Título. Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Observe a diferença: Antes Depois Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Podemos melhor a visualização do valor, incluindo R$ antes do numeral, para isso, iremos utilizar o pipe(|) do thymeleaf para fazer a concatenação. Agora os valores aparecem assim: Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Agora, vamos melhorar a visualização do status. Para isso vamos utilizar um item do bootsrap, o badge. Queremos deixar o pendente na cor vermelha e o recebido na cor verde. Faça uma leitura sobre o badge: https://getbootstrap.com/docs/4.0/components/badge/ Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Vamos criar dentro da classe Titulo, no pacote model, um método que retornar um booleano, para tratarmos o status. Vamos utilizar o método isPendente na pesquisa de títulos. Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Para utilizar a classe badge, teremos 2 situações: Cor verde: badge badge-success Cor vermelha: badge badge-danger Para tratarmos essa situação, utilizaremos o classappend do thymeleaf que irá incluir uma classe (ou badge-success, ou badge-danger) junto a outra classe já existente dentro do elemento html (badge). Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa O código ficará assim: Aqui estamos dizendo que se o título for pendente, vamos mandar inserir a classe badger-danger junto a classe badge dentro do atributo class do elemento. Prof. Pedro Clarindo da Silva Neto Mostrando os itens na página de pesquisa Agora a nossa página de pesquisa ficou assim: Caso não tenha nenhum registro pendente ou recebido, crie para ver o funcionamento na página. Prof. Pedro Clarindo da Silva Neto Validações Atualmente, nossa página de cadastro permite criar registros sem verificar se os dados estão sendo passados pelo formulário: Prof. Pedro Clarindo da Silva Neto Validações Vamos utilizar o Bean Validation para criar algumas regras. O Bean Validation é uma especificação que permite validar objetos com facilidade em diferentes camadas da aplicação. A vantagem de usar Bean Validation é que as restrições ficam inseridas nas classes de modelo. Vale dar uma olhada na documentação:https://beanvalidatio n.org/ Prof. Pedro Clarindo da Silva Neto Validações Na classe Titulo do pacote de modelo, vamos incluir a anotação @NotNull no atributo valor. Desta forma, eu digo que o valor não pode ser null. Prof. Pedro Clarindo da Silva Neto Validações Na classe TituloController, precisamos inserir a anotação @Validated no método salvar, para que o Spring possa validar usando as regras criadas no modelo. Prof. Pedro Clarindo da Silva Neto Validações Se você executar o sistema agora e tentar cadastrar um registro sem o valor, deve aparecer algo parecido com isso: Prof. Pedro Clarindo da Silva Neto Validações O sistema está validando, mas precisamos mostrar uma mensagem mais elaborada e amigável ao usuário. Vamos utilizar um objeto do Spring chamado Errors, que já captura os erros existentes e nos traz uma mensagem sobre o erro. Prof. Pedro Clarindo da Silva Neto Validações Vamos incluir também uma condição dentro de salvar, para que se haja algum erro, ele não continua executando o código. Prof. Pedro Clarindo da Silva Neto Validações Desta maneira, aquela mensagem não irá mais aparecer, pois o sistema irá apresentar novamente a tela de cadastro. Agora precisamos exibir para o usuário uma mensagem. Para conseguirmos obter as mensagens e mostrarmos para o usuário, precisaremos resgatar o objeto titulo que é repassado no controller. Prof. Pedro Clarindo da Silva Neto Validações Na página CadastroTitulo.html, vamos utilizar o elemento th:object do Thymeleaf para receber o titulo do controller e validar os seus campos. Prof. Pedro Clarindo da Silva Neto Validações Agora vamos incluir uma que irá receber as mensagens de erros. Essa div ficará abaixo da div da mensagem de salvo com sucesso. Prof. Pedro Clarindo da Silva Neto Validações Utilizando o objeto utilitário #fields do Thymeleaf, verificamos como o th:if se é retornado algum erro na página. Utilizamos o th:each para percorrer o #fields.detailedErrors, que traz todos as mensagens de erros que foram retornadas e mandamos escrevê-las com o th:text. Prof. Pedro Clarindo da Silva Neto Validações Se acessarmos a página de cadastro agora irá aparecer o seguinte erro: Prof. Pedro Clarindo da Silva Neto Validações Como estamos utilizando a página de cadastros, o objeto titulo ainda não foi passado. Se olharmos no controller, a página de cadastro é passada pelo mapeamento "/novo". Prof. Pedro Clarindo da Silva Neto Validações Para resolver esse problema, utilizamos o addObject, passando um novo título. Desta forma, teremos um objeto titulo quando a página de cadastro for acessada. Prof. Pedro Clarindo da Silva Neto Validações Agora com tudo funcionando, se você tentar salvar um registro sem digitar um valor, a validação será realizada e será exibida uma mensagem ao usuário. Prof. Pedro Clarindo da Silva Neto Validações Podemos customizar essa mensagem, dentro da classe Titulo, na anotação NotNull. Prof. Pedro Clarindo da Silva Neto Validações Agora ficou bem melhor. Prof. Pedro Clarindo da Silva Neto Validações Podemos melhor a visualização para o usuário mostrando o campo que contém o erro. Para isso vamos utilizar a função hasErrors do Thymeleaf, que um campo e retorna um booleano informando se existe algum erro de validação para aquele campo. Como estamos trabalhando com o campo valor, a expressão ficará assim: ${#fields.hasErrors('valor')} Prof. Pedro Clarindo da Silva Neto Validações Vamos fazer esse teste com a função hasErrors e, caso haja algum erro de validação, vamos incluir a classe is-invalid do bootstrap. Faremos isso com o th:classappend qu ejá utilizamos anteriormente. Prof. Pedro Clarindo da Silva Neto Validações Assim, quando o valor precisar ser validado a nova aparência será: Leia sobre formulários e bootstrap: https://getbootstrap.com/docs/4. 0/components/forms/ Prof. Pedro Clarindo da Silva Neto Validações Vamos incluir uma regra para a descrição. Temos 3 anotações interessantes que podemos utilizar: @NotNull: Não permite um valor nulo, porém permite um valor vazio. @NotEmpty: Assim como a @NotNull, não permite valor nulo e além disso seu tamanho deve ser maior que zero. Espaços em brancos são levados em conta na verificação de tamanho do valor. @NotBlank: Assim como a @NotEmpty, não permite valor nulo e o comprimento (sem considerar espaços em branco) deve ser maior que zero. Neste caso, vamos usar o @NotBlank. Prof. Pedro Clarindo da Silva Neto Validações Vamos aproveitar e incluir uma regra para que a descrição não tenha mais de 60 caracteres com a anotação @Size. Prof. Pedro Clarindo da Silva Neto Validações E também vamos incluir uma classe is-invalid, caso haja erro na validação da descrição na página de cadastro. Prof. Pedro Clarindo da Silva Neto Validações Faça os testes com a descrição sem nenhuma informação e também com mais de 60 caracteres. Prof. Pedro Clarindo da Silva Neto Validações Vamos delimitar um intervalo de valores para o campo valor com a anotações @DecimalMin e @DecimalMax Prof. Pedro Clarindo da Silva Neto Validações TAREFA: Atualize seu código para que faça as validações e mostre a seguinte tela quando nada for digitado: Prof. Pedro Clarindo da Silva Neto Validações Vamos aproveitar que podemos reutilizar as mensagens em nosso projeto e vamos separá-la do arquivo de Cadastro. Primeiramente, vamos criar no diretório Templates, o arquivo Mensagem.html Prof. Pedro Clarindo da Silva Neto Validações Retiramos as mensagens da página de Cadastro e colocamos no arquivo Mensagem.html Prof. Pedro Clarindo da Silva Neto Validações No lugar das mensagens que foram retiradas iremos adicionar o novo arquivo de mensagem, utilizando o th:replace. Prof. Pedro Clarindo da Silva Neto Validações Teste novamente a tela de cadastro e veja se as mensagens estão funcionando como antes: Prof. Pedro Clarindo da Silva Neto Usando o th:field para manter valor Agora, como o sistema realizando nossas validações, enfrentamos o seguinte cenário: Quando o formulário é validado e há um erro, a mensagem ao usuário aparece, mas os dados já digitados pelo usuário e que estavam corretos desaparecem. Prof. Pedro Clarindo da Silva Neto Usando o th:field para manter valor Neste caso, vamo utilizar o th:field do Thymeleaf para arrumar o código da página de cadastro. O th:field substitui o name. O th:field indicará que aquele input é um campo do objeto título, definido em th:object. Prof. Pedro Clarindo da Silva Neto Usando o th:field para manter valor Desta forma, o valor digitado é mantido após a validação. Prof. Pedro Clarindo da Silva Neto Usando o th:field para manter valor Fazer a mudança nos outros campos do formulário. Prof. Pedro Clarindo da Silva Neto Redirecionando para nova requisição Agora temos outro problema: depois de salvar no banco as informações continuam aparecendo no formulário. Prof. Pedro Clarindo da Silva Neto Redirecionando para nova requisição Precisamos alterar o nosso o método salvar no Controller. Utilizaremos o redirect para que seja realizada uma nova requisição no navegador e o RedirectAttributes para enviar atributos nesse redirecionamento. Utilizado para redirecionar a mensagem URL repassada pelo redirect. Prof. Pedro Clarindo da Silva Neto Implementando a edição Neste momento iremos adicionar mais uma funcionalidade para a aplicação. Agora que estamos salvando e validando, chegou a hora de editar o conteúdo. Vamos utilizar a última coluna da página de Pesquisa para adicionar a opção de edição. Prof. Pedro Clarindo da Silva Neto Implementando a edição Dentro de LayoutPadrao, vamos inserir o link para usarmos o Material Icons. Cada ícone é criado usando nossas diretrizes de design para representar em formas simples e mínimas os conceitos universais usados comumente em uma UI. Fazer a leitura: https://google.github.io/ material-design-icons/ Prof. Pedro Clarindo da Silva Neto Implementando a edição Na página de Pesquisa, vamos inserir um ícone para a edição. Prof. Pedro Clarindo da Silva Neto Implementando a edição Nosso ícone de edição já está disponível: Prof. Pedro Clarindo da Silva Neto Implementando a edição Para adicionar um link ao ícone de edição, é necessário ter uma estrutura que seja repassada para que o link seja criado automaticamente e repasse o Id de cada um dos registros, algo do tipo "localhost:8080/alguma-coisa/id". Desta forma, é possível recuperar os dados que se deseja editar. Dentro do controller vamos criar a edição. Prof. Pedro Clarindo da Silva Neto Implementando a edição Dentro do RequestMapping eu passo o código que eu vou utilizar para referenciar os registros. Então, quando a aplicação passar uma url do tipo /titulos/5, ele estará mapeado para a edição, neste caso o registro que tenha o ID 5. Prof. Pedro Clarindo da Silva Neto Implementando a edição @PathVariable é utilizado quando o valor da variável é passada diretamente na URL, mas não como um parâmetro que você passa após o sinal de interrogação (?) mas sim quando o valor faz parte da url. Prof. Pedro Clarindo da Silva Neto Implementando a edição Como é passado um codigo e um Titulo, o Spring sabe qual é o registro de qual estamos nos referindo. Perceba que não precisamos realizar nenhum tipo de método de busca a partir do codigo. Não é demais?!?!? Prof. Pedro Clarindo da Silva Neto Implementando a edição Passamos no ModelAndView a nossa página de Cadastro, e o no addObject o titulo que tem o codigo que foi passado no PathVariable. O que será retornado para o usuário é a página de Cadastro com as informações do registro que foi solicitado. Prof. Pedro Clarindo da Silva Neto Implementando a edição Faça o teste. Aqui eu vou editar o Quibe, que tem o id 1. Vou digitar no navegador (veja qual item do seu projeto você irá editar). Vou digitar localhost:8080/titulos/1 Prof. Pedro Clarindo da Silva Neto Implementando a edição Veja que as informações já vieram carregadas. Isso porque utilizamos na página de Cadastro o th:object e o th:field, assim recebemos o objeto titulo e conseguimos preencher os campos. Prof. Pedro Clarindo da Silva Neto Implementando a edição Alterei o valor do quibe de 18,00 para 50,00. A mensagem de salvo com sucesso apareceu. Vou verificar na página de Pesquisa. Ao invés de alterar, foi criado um novo! Prof. Pedro Clarindo da Silva Neto Implementando a edição Isso acontece, pois quando eu estou editando os dados no formulário de Cadastro, o Spring não sabe que já é um novo registro. Para isso precisamos passar o campo que representa a ID para que ele saiba que é um registro existente. Vamos adicionar no Cadastro esse campo. Prof. Pedro Clarindo da Silva Neto Implementando a edição Desta vez vou editar o Bolo de Chocolate, que tem a ID 5. Prof. Pedro Clarindo da Silva Neto Implementando a edição Desta vez vou editar o Bolo de Chocolate, que tem a ID 5. Prof. Pedro Clarindo da Silva Neto Implementando a edição Agora sim, o registro foi alterado! Prof. Pedro Clarindo da Silva Neto Implementando a edição Precisamos agora criar o link dinâmico na página de Pesquisa, pois atualmente estamos digitando manualmente a URL. Usamos o th:href do Thymeleaf para montar a nossa URL. Prof. Pedro Clarindo da Silva Neto Implementando a edição O @{} é uma expressão do Thymeleaf que auxilia na construção de links e me permite criar variáveis para montar esses links e repassamos o titulo.codigo que será utilizado como valor. Variáveis criadas pelo programador Prof. Pedro Clarindo da Silva Neto Implementando a edição Vá para página de pesquisa e veja os ícones de edição. Teste-os e veja se as URL estão bem formadas e se os códigos estão corretos. Prof. Pedro Clarindo da Silva Neto Deletando os registros Agora que já conseguimos alterar os nossos registro, vamos entender como deletá-los. Vamos mostrar ao usuário uma janela modal para que, quando o usuário clicar no botão de deletar, seja feita uma pergunta se ele realmente deseja apagar aquele registro. Para isso, vamos utilizar o modal do Bootsrap. Faça a leitura: https://getbootstrap.com/do cs/4.0/components/modal/ Prof. Pedro Clarindo da Silva Neto Deletando os registros Para o modal funcionar, precisaremos o arquivo.js do bootstrap, que já está no nosso projeto e está sendo chamado no nosso LayoutPadrao. Criaremos um arquivo html que armazenará o conteúdo do nosso modal. É o DialogoConfirmacaoModal.html Prof. Pedro Clarindo da Silva Neto Deletando os registros Dentro do nosso arquivo de Pesquisa, vamos inserir o DialogoConfirmacaoModal Prof. Pedro Clarindo da Silva Neto Deletando os registros Ainda no arquivo de Pesquisa, vamos inserir um botão para o usuário clicar. Para que nosso botão funcione com o modal precisamos passar dois atributos: data-toogle e data-target. Atributos data-* nos permitem armazenar informações extras em elementos HTML padrões e semânticos. Estou passando o #confirmacaoExclusaoModal Como valor do data-target. O botão irá aparecer logo depois do link de editar. Prof. Pedro Clarindo da Silva Neto Deletando os registros Agora temos um ícone para editar e outro para excluir. Prof. Pedro Clarindo da Silva Neto Deletando os registros Nosso arquivo DialogoConfirmacaoModal.html ficará assim: A maior parte dessa estrutura veio do modelo da página do Bootstrap. Prof. Pedro Clarindo da Silva Neto Deletando os registros Repare que passamos como id, o confirmacaoExclusaoModal Lembre-se que ele foi referenciado no data-target da página de Pesquisa. Prof. Pedro Clarindo da Silva Neto Deletando os registros Outra coisa importante é o formulário criado, que possui um input hidden e passa o método DELETE. Esse formato é conhecido como hidden method, onde eu posso enviar um método diferente dentro de um input hidden. Desta forma conseguiremos mapear o DELETE no Controller. Prof. Pedro Clarindo da Silva Neto Deletando os registros Para que a página de Pesquisa, o modal e o Controller troquem informações entre si. Para isso, utilizaremos a biblioteca JQuery. Vamos criar na pasta js, o arquivo cobranca.js. Prof. Pedro Clarindo da Silva Neto Deletando os registros Precisamos adicionar esse arquivo no LayoutPadro.html Prof. Pedro Clarindo da Silva Neto Deletando os registros O nosso arquivo cobranca.js ficará assim: Prof. Pedro Clarindo da Silva Neto Deletando os registros Para conseguirmos capturar o codigoTitulo e o descricaoTitulo, precisamos alterar o nosso botão excluir na página de Pesquisa. O th:attr, do Thymelef, vai gerar os atributos data-codigo e data-descricao que precisamos. Prof. Pedro Clarindo da Silva Neto Deletando os registros Vamos alterar também o form do DialogoConfirmacaoModal.html. O th:attr, vai nos informar o url-base que estamos resgatando no arquivo cobranca.js. Prof. Pedro Clarindo da Silva Neto Deletando os registros Feito isso, precisamos criar o excluir no Controller. Neste método, quando o nosso mapeamento /titulos, receber de ID e o método DELETE, ele irá chamar o nosso método. Iremos usar o médoto deleteById do JpaRepository e informaremos o código do nosso registro. Depois enviaremos a mensagem ao usuário de excluído com sucesso. Prof. Pedro Clarindo da Silva Neto Deletando os registros Para que a mensagem apareça na nossa página de Pesquisa, precisamos incluí-la, como fizemos na página de Cadastro. Prof. Pedro Clarindo da Silva Neto Deletando os registros Quando executarmos nossa página de Pesquisa aparecerá um erro como esse: Prof. Pedro Clarindo da Silva Neto Deletando os registros Isso acontece porque nossa página de Mensagem ela busca nas mensagens de Erro o fields.hasAnyErrors, usado para quando temos um formulário. Neste caso precisaremos criar um arquivo de mensagens para Erro e outro para as demais mensagens. Prof. Pedro Clarindo da Silva Neto Deletando os registros Em MensagemErro.html ficaremos com esse conteúdo: Prof. Pedro Clarindo da Silva Neto Deletando os registros Em Mensagem.html ficaremos com esse conteúdo: Prof. Pedro Clarindo da Silva Neto Deletando os registros Em CadastroTitulo.html vamos inserir a página de Erro: Em PesquisaTitulos.html deixamos só a Mensagem. Prof. Pedro Clarindo da Silva Neto Deletando os registros Agora vamos testar nosso excluir. Observe os campos repassados. Prof. Pedro Clarindo da Silva Neto Deletando os registros Ao clicar no botão excluir, o modal é acionado e tem como valor atributo action o /titulos/1 Prof. Pedro Clarindo da Silva Neto Deletando os registros E pronto, registro excluído! Prof. Pedro Clarindo da Silva Neto Deletando os registros Em alguns casos, o Spring não consegue reconhecer os Hidden Methods automaticamente. Para que isso aconteça, precisamos especificar a seguinte propriedade no arquivo application.properties. Prof. Pedro Clarindo da Silva Neto Referências Primeiros Passos com Spring MVC. Algaworks, 1a ed, 2016. Começando com Spring MVC, Algaworks, 2019. Produtividade no Desenvolvimento de Aplicações Web com Spring Boot. Algaworks, 3a ed, 2017. Validação com Bean Validation.Disponível em:, 2020 Começando com Apache Maven em projetos Java. Disponível em: Introdução ao Maven. Disponível em: Entendendo o equals e hashcode. Disponível em: < https://blog.algaworks.com/entendendo-o-equals-e-hashcode/> Injeção de Dependências com Spring. Disponível em: CRUD com Spring e Thymeleaf. Disponível em: Thymeleaf. Disponível em: Bean Validation, diferença entre: @NotNull,@NotEmpty e @NotBlank.Disponível em:, 2020. Utilizando Data Attributes. Disponivel em:. Acesso 10 set. 2020. Prof. Pedro Clarindo da Silva Neto