Você está na página 1de 89

10/04/2023, 21:18 Camada de visão

Camada de visão
Prof. Denis Cople

Descrição

Utilização de ferramentas como Thymeleaf e Bootstrap na construção da camada View de uma arquitetura
MVC para Web, em sistemas baseados no framework Spring, viabilizando a criação de interfaces
responsivas e design profissional, com pouco esforço de programação.

Propósito

Definir interfaces de sistemas Web criados com o framework Spring, com grande produtividade,
obedecendo ao padrão arquitetural MVC, além da garantia de responsividade, por meio de ferramentas
como Thymeleaf e Bootstrap, as quais viabilizam a criação de interfaces com design profissional.

Preparação

Antes de começar, é necessário configurar o ambiente com a instalação do JDK, Spring Tools Suite e
NetBeans completo, em versão com suporte a projetos Maven, além de adicionar o servidor Tomcat EE na
instalação da IDE. Também será necessário acessar a internet tanto para testes quanto para o download de
artefatos via Maven. Por fim, acesse os arquivos dos projetos desenvolvidos.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 1/89
10/04/2023, 21:18 Camada de visão

Objetivos

Módulo 1

Implementação de uma página simples da web


Reconhecer as sintaxes básicas utilizadas na Web para definição de páginas.

Módulo 2

CRUD utilizando o framework Thymeleaf


Aplicar o Thymeleaf por meio de templates para definição da camada View do MVC.

Módulo 3

Estudo de caso com Framework Bootstrap


Empregar o Bootstrap na construção da interface para garantia de produtividade.

meeting_room
Introdução

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 2/89
10/04/2023, 21:18 Camada de visão

Abordaremos os elementos necessários para a construção de interfaces de usuário robustas, com


responsividade e aspecto profissional, por meio de ferramentas utilizadas amplamente no mercado. Nosso
foco inicial será na compreensão das sintaxes básicas para a construção de páginas, incluindo HTML, Java
Script e CSS, além da utilização de JQuery UI.

Na sequência, veremos como pode ser feita a integração com sistemas Spring Web, por meio de templates
do Thymeleaf, dentro de uma arquitetura MVC, de forma muito simples e concisa.

Por fim, aplicaremos o framework Bootstrap em um sistema cadastral completo, com a definição de telas
alinhadas aos melhores princípios de design e responsividade exigidos pelo mercado, além de incluir os
componentes de segurança necessários para definir um modelo de autenticação básico, integrando-se às
interfaces criadas com muita fluidez.

1 - Implementação de uma página simples


da web
Reconhecer as sintaxes básicas utilizadas na Web para definição de
páginas.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 3/89
10/04/2023, 21:18 Camada de visão

HTML 5
A linguagem HTML (Hypertext Markup Language) fornece a base estrutural para as páginas disponibilizadas
na Internet. Visa estruturar a página com base em tags, ou etiquetas, em que temos uma Q, segundo o perfil
de exibição, formulários de cadastro e elementos para a navegação entre páginas. Inclusive, o nome
hipertexto se refere à capacidade de navegação ao longo do texto.

Sintaxe
A sintaxe XHTML equivale ao HTML 4.0 Strict, que evoluiu para o HTML 5.

Toda página apresenta um cabeçalho (head), em que temos o título (title) apresentado no topo da janela do
navegador, ligações (link) com recursos externos, folhas de estilo e demais elementos de uso geral. Na
sequência, deve ser definido o corpo da página (body), contendo a parte visual de nosso documento.

No corpo do documento, temos elementos estruturais de texto, como a utilização de fontes padronizadas
para títulos, delimitação de parágrafos e criação de listas. Embora o HTML não diferencie maiúsculas e
minúsculas, as páginas serão validadas na W3C apenas se as tags forem escritas com letras minúsculas.
Vejamos algumas tags:

Tags Utilização

h1, h2, h3, h4, h5, Aplica a formatação padronizada para títulos, em que h1 utiliza fonte
h6 maior, e vai diminuindo com a numeração.

Enquanto p define um parágrafo, br é uma quebra de linha simples, e hr


br, hr, p
efetua a quebra com o desenho de uma linha horizontal.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 4/89
10/04/2023, 21:18 Camada de visão

Tags Utilização

Listas com marcadores numéricos são definidas com o uso de ol,


ul, ol, li enquanto as simbólicas utilizam ul. Em ambos os casos, itens são
definidos com li.

Tabela: Tags básicas HTML


Denis Cople.

Tags básicas
Vejamos uma aplicação no Exemplo001.html.

HTML
content_copy

A tag meta permite definir metadados, aqui definida a página de código UTF-8, permitindo o uso de
acentuação em palavras da língua portuguesa. No HTML, também temos símbolos especiais, chamados de
entidades, que são iniciadas com ‘e comercial &’ e fechadas com ponto e vírgula, como b, representando o
símbolo de copyright.

Outro elemento é o comentário utilizado no HTML, iniciado com sinal de exclamação e duas subtrações, e
fechado com duas subtrações.
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 5/89
10/04/2023, 21:18 Camada de visão

Abrindo a página no navegador, teremos o resultado a seguir. Para facilitar os testes, podemos criar um
aplicativo Web, no NetBeans, e acrescentar a página HTML.

Visualização de Exemplo001.html

Tabelas
Nas tabelas, temos uma divisão em linhas, e cada linha com suas respectivas colunas, definindo células de
informação. Com base em atributos como colspan e rowspan, as células podem ser combinadas, e ainda
temos a possibilidade de uma linha de cabeçalho. Vejamos algumas tags:

Tags Utilização

Define uma tabela, podendo ter borda e


table
largura especificados.

tr Define uma linha da tabela.

Definem células de informação, ou colunas,


td, th na linha, sendo que th é utilizada no
cabeçalho.

thead, tbody, tfoot Definem trechos de cabeçalho, corpo e


rodapé na tabela, para que ocorra o

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 6/89
10/04/2023, 21:18 Camada de visão

Tags Utilização

reconhecimento a partir de outras


ferramentas.

Tabela: Tags para desenho de tabelas.


Denis Cople.

O uso de tabelas é indicado para a exibição de dados tabulares, como a seguir.

HTML
content_copy

A tabela foi criada com alguns atributos visuais, incluindo a borda de espessura 1 e utilização de 100% do
espaço horizontal disponível. Note o uso de colspan na primeira e última linhas, em que células
subsequentes são mescladas, com base no valor definido por meio do atributo.

Vejamos a saída da página Exemplo002.html.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 7/89
10/04/2023, 21:18 Camada de visão

Visualização de Exemplo002.html

Formulários
Nos formulários, podemos contar com os componentes mais tradicionais das interfaces de usuário, como
botões, caixas de texto e caixas de seleção. Vejamos algumas tags:

Tags Utilização

Define um formulário, sendo necessário


form indicar o endereço para onde as informações
serão enviadas e o método HTTP utilizado.

Desenha um componente de entrada, em que


o atributo type permite a escolha de sua
Input aparência, podendo ser text, button,
checkbox, radio, reset ou submit, em que os
últimos são os botões de reinício e envio.

Expressam elementos de entrada


multivalorados, ou seja, as caixas de seleção
Select, datalist
em que os valores são expressos na forma
de listas.

Define um componente de entrada para


Textarea textos maiores, permitindo a quebra de
linhas.

Utilizado para descrever um campo do


Label formulário. É muito útil para otimizar a
visualização em dispositivos móveis.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 8/89
10/04/2023, 21:18 Camada de visão

Tags Utilização

Utilizados para configurar grupos de campos


Fieldset, legend de entrada, com a adição de uma legenda e
uma borda.

Tabela: Tags para criação de formulários.


Denis Cople.

Para textos maiores, devemos utilizar o textarea, que permite quebra de linhas, sendo configurado em
termos do número de linhas e colunas.

Quanto a elementos multivalorados, como listas, temos as opções select e datalist, ambos definindo os
elementos da lista por meio de option. No entanto, o datalist deve ser utilizado para pequenos conjuntos de
valores fixos, enquanto o select, que permite o uso de uma chave e um texto para a opção, reflete melhor um
conjunto dinâmico.

Vejamos componentes no Exemplo003.html.

HTML
content_copy

Nosso formulário tem como destino um endereço fictício, associado por meio de action, usando o método
POST do protocolo HTTP. Após o preenchimento dos dados, o clique no componente do tipo submit, ou

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 9/89
10/04/2023, 21:18 Camada de visão

botão de envio, tentará enviar os dados em background para o endereço, o que causará um erro de acesso,
mas, no caso de uma rota real, estaria enviando esses dados para um componente do servidor capaz de
tratá-los, como um Servlet, por exemplo.

O id deve ser utilizado nos relacionamentos internos da página, enquanto name define a variável que será
enviada para o servidor. O value define o valor que será enviado para o servidor, associado à variável
definida via name, devendo ser fixado para todos os componentes que não permitem edição de valor via
teclado.

A lista de valores simples datalist deve ser associada ao componente do tipo input por meio do atributo list.
Note o uso de id para o relacionamento, da mesma forma que nas tags do tipo label, para associação com
os componentes corretos.

O metadado viewport, de grande utilidade na garantia da responsividade, configura a página para se


adequar ao espaço de visualização oferecido pelo dispositivo.

Executando a página no navegador, teremos a tela de entrada.

Formulário Exemplo003.html.

MathML
O MathML é uma linguagem de marcação para exibir e capturar estruturas e conteúdo matemático.
Vejamos um Exemplo004.html.

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 10/89
10/04/2023, 21:18 Camada de visão

A sintaxe MathML é bastante complexa e extensa, mas a listagem nos traz muitos elementos de utilização
comum. Inicialmente, definimos uma linha principal com mrow, e na sequência, temos a integral e seus
limites, dentro de msubsup, com o símbolo em mo, limite inferior em mn e limite superior em mi.

O conteúdo interno da integral será uma fração, com mfrac, em que a parte superior deve ficar em uma tag
mrow, a qual envolve, no exemplo, um logaritmo na base 3, definido com msub, com a função em mi e a
base em mn, seguido da variável x na tag mi, enquanto a parte inferior tem apenas a variável x em uma tag
mi. Na última parte, temos o sinal diferencial, em uma tag mo, seguido da variável para integração x na tag
mi.

Toda a expressão matemática deve ser encapsulada em uma tag math, em que devemos estar atentos para
a utilização do namespace adequado. Para testar, devemos utilizar o Firefox, pois nem todos os
navegadores oferecem suporte direto ao MathML, sendo necessário adicionar plugins a navegadores como
Chrome e Edge.

Apresentação do Exemplo004.html, via Firefox.

Âncoras
As âncoras, com base na tag a, definem a navegação entre páginas e conteúdo, justificando a classificação
dos documentos como hipertexto. Uma âncora pode definir um local dentro de uma página extensa, navegar
para o trecho nomeado, ou definir um link para algum endereço. É bastante comum sua utilização junto a
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 11/89
10/04/2023, 21:18 Camada de visão

imagens, incorporadas às páginas por meio da tag img.

Vejamos o Exemplo005.html.

HTML
content_copy

Como um dos objetivos é demonstrar a navegação interna da página, para situações em que o conteúdo é
muito extenso, foram adicionadas muitas quebras de linha. Para marcar o local da página, utilizamos o
atributo id da âncora, enquanto a navegação para o trecho ocorre com o uso do valor de id, precedido por
cerquilha, no atributo href.

A navegação para outros sites ou páginas também é definida no atributo href, com o descritivo da âncora
colocado entre a tag e seu fechamento. No lugar do texto descritivo, podemos usar uma imagem (img),
definindo um ícone clicável.

O resultado da execução da página, que receberá o nome Exemplo005.html, é apresentado a seguir. Como
temos uma página extensa, foi dividida em duas partes, em que o clique sobre a âncora com texto "própria"
levará para o final dela.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 12/89
10/04/2023, 21:18 Camada de visão

Visualização do Exemplo005.html.

CSS

Folhas de estilo
Com o papel estrutural que o HTML assumiu, vários dos atributos de configuração tipográfica das versões
antigas se tornaram obsoletos, deslocando-se a responsabilidade para as folhas de estilo, ou CSS (Cascade
Style Sheets).

As folhas de estilo podem ser adicionadas na tag do HTML (inline), em um trecho delimitado por style, ou
em um arquivo externo. Em termos de reutilização e responsividade, a melhor opção é o uso de arquivo
externo, pois permite centralizar as formatações e versionar para cada plataforma, ou seja, utilizar pontos
de quebra para formatações específicas.

Vamos voltar ao primeiro exemplo de HTML e aplicar algumas formatações sobre as tags, adotando um
setor delimitado por style.

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 13/89
10/04/2023, 21:18 Camada de visão

Aqui definimos elementos comuns para algumas tags visuais, como cor da fonte (color), cor do fundo
(background-color) e alinhamento do texto (text-align). Também temos uma borda do tipo tracejada sendo
aplicada ao redor das listas.

Podemos aplicar as formatações a várias tags simultaneamente, desde que as separemos por vírgula, e
qualquer atributo definido será combinado com as formatações já existentes. Aliás, as folhas de estilo são
denominadas como "em cascata" porque podem ser sobrepostas.

Qualificador hover
O qualificador hover permite definir uma formatação para o momento em que o mouse repousa sobre o
componente. No exemplo, a página tem fundo preto e fonte branca como padrão, mas, quando o mouse
passa sobre um parágrafo, ele muda a cor de fundo para marrom.

Formatações aplicadas às tags do arquivo Exemplo001.html.

Para formatar um elemento específico da página, o seletor correto seria um identificador, ou id, em que uma
utilização comum é na criação de áreas para organização do conteúdo. Como o padrão tableless
desencoraja o uso de tabelas com esse fim, o uso de áreas identificadas, com base em tags do tipo div,
formatadas via CSS, transformou-se na estratégia preferencial.

Identificadores são voltados para a individualização de algum componente na página, sendo definidos na
folha de estilo com um nome precedido de cerquilha. Para que a formatação seja utilizada, devemos ter um
componente com atributo id utilizando o mesmo nome.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 14/89
10/04/2023, 21:18 Camada de visão

Exemplos práticos

Exemplo 1
A seguir, um arquivo de folha de estilos com o nome Exemplo006.css.

CSS
content_copy

De acordo com a formatação adotada, toda tag div definirá uma área com largura (width) de 200 pixels e
altura (height) de 150 pixels, utilizando texto alinhado ao centro e tamanho de fonte ajustado para 40 pixels.
Em seguida, temos a individualização das características para cada uma das áreas que será criada. A
combinação das formatações da div e do identificador definirão o posicionamento e as dimensões dessas
áreas.

Nas formatações específicas, temos a definição da cor de fundo (background-color), estilo da borda (boder-
style), e posicionamento absoluto, em relação ao limite superior esquerdo da página, considerado como
origem dos eixos horizontal e vertical. Com os valores utilizados, teremos uma área a 10 pixels do topo e 10
pixels da esquerda, e outras duas áreas utilizando os valores 110 e 210, respectivamente.

A página Exemplo006.html, com a listagem a seguir, utiliza a folha de estilos definida anteriormente.

HTML
content_copy
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 15/89
10/04/2023, 21:18 Camada de visão

A página é bastante simples, com a definição das áreas por meio de tags do tipo div, relacionadas aos
estilos específicos por meio do atributo id. Devemos lembrar que teremos a combinação das formatações
para a tag e para o identificador em cada área.

O relacionamento entre os arquivos HTML e CSS foi definido por meio da tag link, em que temos o atributo
rel com o valor stylesheet (folha de estilos), e o nome do arquivo em href. Vejamos o resultado da interface:

Exemplo de CSS.

Ao contrário dos identificadores, que definem formatações para elementos específicos, as classes,
definidas com a utilização de ponto antes do nome, servem para formatar elementos que se repetem ao
longo da página.

Exemplo 2
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 16/89
10/04/2023, 21:18 Camada de visão

Vamos criar a página Exemplo007.html, contendo a listagem a seguir.

HTML
content_copy

O que temos no código é a definição de uma lista principal, em que os itens são links para outras páginas e
endereços, além de um item contendo outra lista, o que seria um submenu, com mais alguns links. A relação
com a folha de estilos ocorre por meio da tag link, na divisão head, a qual não terá efeito antes da criação do
arquivo.

Página com menu, sem a folha de estilos.

Como podemos observar, temos a exibição das listas, contendo as âncoras, em que os links estão
funcionais, mas ainda sem a formatação adequada. Veremos que as folhas de estilos efetuam
modificações extremas na forma de apresentação, permitindo que o HTML assuma apenas o papel
estrutural, de acordo com a divisão de responsabilidades exigida pela W3C.

Vamos estilizar nosso menu por meio da criação do arquivo Exemplo007.css, contendo a listagem a seguir.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 17/89
10/04/2023, 21:18 Camada de visão

CSS
content_copy

Se voltarmos ao nosso código HTML, veremos que a lista principal, na primeira tag ul, tem o valor menu no
atributo class, definindo a utilização das formatações associadas à classe menu, da folha de estilos. Da
mesma forma, a lista interna é atribuída à classe submenu, que também será especificada na folha de
estilos.

Começamos com uma formatação geral, por meio do asterisco, para a remoção das margens da página,
além da definição da fonte com 12 pixels, na tag body. Nos passos seguintes, temos as classes menu e
submenu sendo configuradas.

A classe menu remove o marcador dos itens de lista para todos os


elementos internos, com base no atributo list-style, além de usar cor de
fundo amarela e posicionamento relativo à esquerda da página, por
meio do valor left no atributo float, para cada item. Para o submenu,
temos posicionamento de 25 pixels em relação ao topo do contêiner
atual, no caso o item do menu, e fundo laranja, não sendo visível
inicialmente, devido ao uso de none para display.

As demais formatações apresentam duas características interessantes na criação de seletores: o


agrupamento e a dependência. Podemos agrupar seletores separados por vírgula, em que a mesma
formatação é aplicada a todos, ou especificar uma dependência por meio do uso de espaço, em que o estilo

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 18/89
10/04/2023, 21:18 Camada de visão

é aplicado apenas quando a hierarquia é observada.

Segundo as características definidas, uma tag li, dentro de um elemento menu, respeitará uma sequência de
posicionamento a partir da esquerda, além de apresentar uma borda tracejada de 1 pixel à direita (border-
right).

Da mesma forma, na formatação seguinte, temos as âncoras dentro das tags li, a partir de menu, com
remoção do sublinhado, por meio de text-decoration, definição do espaçamento em padding, e visualização
(display) como bloco, em que temos a área preenchida, sem outros elementos HTML ao redor, a não ser que
sejam configurados com valor left em float.

Ainda com relação às âncoras, o qualificador hover fará com que seja
utilizado fundo preto e fonte branca quando o mouse estiver sobre
elas.

Temos ainda a formatação para a tag li, a partir de submenu, com definição da borda inferior, visualização
em bloco e largura de 120 pixels. Como o submenu estará dentro de menu, temos formatações que se
propagam para li, como a borda direita, ao mesmo tempo em que, devido à precedência da visualização do
contêiner, as tags li de submenu ficarão invisíveis no início.

Para que o submenu fique visível, temos uma formatação muito específica, em que o qualificador hover é
aplicado uma tag li de menu sequenciada por ul, mudando o valor do atributo display da ul para block
enquanto o mouse estiver sobre o item. Vejamos a interface resultante:

Página com menu, utilizando a folha de estilos.

Java Script
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 19/89
10/04/2023, 21:18 Camada de visão

O dinamismo das páginas exige a utilização de uma linguagem de programação adequada, no caso o Java
Script, e interação baseada na utilização de eventos.

Utilizamos o Java Script para controle de elementos da página HTML e sua interatividade, em que o código
pode ser incluído na própria página, ou organizada no formato de biblioteca, como um arquivo externo.
Caracterizada originalmente como uma linguagem para o navegador, hoje temos muitas tecnologias que
adotam Java Script no lado servidor, como NodeJS.

Imagem ilustrativa JavaScript.

Uma variável pode ser declarada com o uso de var, ou simplesmente por meio da inicialização. Como o Java
Script não é fortemente tipado, a variável assume o tipo do valor associado a ela. Os tipos com os quais a
linguagem trabalha são: numérico, booleano, texto, objeto e vetor, este último como objeto da classe Array.

Operadores do Java Script


Vamos começar pela criação da página Exemplo008.html.

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 20/89
10/04/2023, 21:18 Camada de visão

No exemplo, são declaradas três variáveis, com a utilização de var, sendo efetuadas algumas operações
aritméticas sobre elas. A cada passo, é impresso na página o valor das variáveis, dentro de tags do tipo li,
por meio de document.writeln, com a concatenação dos valores no texto efetuada pelo sinal de adição.

Com relação aos operadores do Java Script, podem ser observados na tabela seguinte:

Operador Tipo Utilização

Operação de adição. Quando colocado à


esquerda da igualdade, o valor é somado à
+ += ++ Aritmético
variável receptora. Duplo mais incrementa um.
Também é utilizado na concatenação de texto.

Operação de subtração. Quando posicionado à


- -= -- Aritmético esquerda, temos a subtração do valor no
receptor. Duplo menos decrementa um.

Multiplicação de valores. Quando posicionado à


* *= Aritmético esquerda, temos a multiplicação do receptor
pelo valor.

Operação de divisão. Quando posicionado à


/ /= Aritmético esquerda, temos a divisão do receptor pelo
valor.

Resto da divisão inteira. Quando posicionado à


% %= Aritmético esquerda, obtemos o resto da divisão do
receptor pelo valor.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 21/89
10/04/2023, 21:18 Camada de visão

Operador Tipo Utilização

Comparação entre valores, dos tipos maior e


> >= Relacional
maior ou igual, com resultado do tipo booleano.

Comparação entre valores, dos tipos menor e


< <= Relacional menor ou igual, com resultado do tipo
booleano.

== === Comparação entre valores, dos tipos igualdade


Relacional e diferença, com resultado do tipo booleano.
!= Permite comparação de texto.

Operador lógico and (e). Requer dois valores


&& Lógico
booleanos.

Operador lógico or (ou). Requer dois valores


|| Lógico
booleanos.

Operação de negação. Inverte o resultado da


! Lógico
operação lógica.

Tabela: Operadores oferecidos na sintaxe do Java Script.


Denis Cople.

A divisão inteira trunca o valor no Java, mas não no Java Script, pois não temos como diferenciar entre
inteiro e ponto flutuante. Outra diferença para o Java é a comparação de texto: no Java, é necessário o
método equals, enquanto o Java Script adota o operador de igualdade padrão.

Vejamos a interface gerada:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 22/89
10/04/2023, 21:18 Camada de visão

Utilização de Java Script em Exemplo008.html.

Estrutura condicional
A similaridade entre Java Script e derivados do C também ocorre na sintaxe para as estruturas de decisão e
de repetição. Vejamos um exemplo de estrutura condicional, no arquivo Exemplo009.html.

HTML
content_copy

A função prompt serve para solicitar ao usuário a digitação de um valor a partir de um diálogo de entrada,
enquanto a função eval efetua a conversão do texto para número. De acordo com nosso exemplo, a variável
x recebe o valor digitado pelo usuário, com o uso da função prompt, ocorrendo a conversão para numérico
por meio de eval.

Com base no valor digitado, a página apresentará uma das alternativas de frase, sempre com o

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 23/89
10/04/2023, 21:18 Camada de visão

encapsulamento na tag h1, ocorrendo a escolha da frase pela estrutura condicional if..else, segundo a
condição x > 5. Vejamos o resultado final:

Execução da página Exemplo009.html, com estrutura condicional.

As funções, bem como os métodos da orientação a objetos, são processos nomeados, que podem ou não
apresentar parâmetros e retornar valores. Criamos funções no Java Script com o uso de function, e elas
podem retornar valores para o chamador por meio de return.

Biblioteca Java Script


Vamos começar com a definição do arquivo ExemploLib.js, em que teremos uma biblioteca Java Script.

JavaScript
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 24/89
10/04/2023, 21:18 Camada de visão

Nessa biblioteca, temos duas funções: cálculo do fatorial e a verificação se o número fornecido é primo. Em
ambos os casos, temos um parâmetro de entrada x e uso de return para fornecimento do resultado, embora
não sejam elementos obrigatórios.

A função fatorial é recursiva, com base em uma condicional, em que


valores menores do que 2 causam o retorno de 1, enquanto outros
especificam o retorno a partir da multiplicação do valor pelo fatorial
do anterior.

Já para o teste de primalidade, ele foi codificado com base em uma estrutura de repetição, em que ocorre o
retorno de false quando o parâmetro é divisível por algum valor do loop, segundo o teste do resto da divisão,
ou true, após o loop, quando não é divisível por nenhum dos valores, o que é justificado pela regra de que o
número primo só pode ser dividido por 1 ou por ele mesmo.

Com nossa biblioteca Java Script pronta, vamos criar o arquivo Exemplo010.html.

HTML
content_copy

O primeiro ponto a ser observado é a inclusão da biblioteca criada anteriormente, ao nível da divisão head
de nossa página. Basta utilizar o atributo src de script, tendo como valor o nome da biblioteca, ou seja,
ExemploLib.js.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 25/89
10/04/2023, 21:18 Camada de visão

Temos duas tags div, utilizadas para dividir a página em duas colunas. Dentro de cada uma, são definidas
estruturas de repetição para a chamada das funções. Ambas as colunas terão largura de 200 pixels, sendo
posicionadas lado a lado, partindo da esquerda.

Temos a impressão dos fatoriais de 3 a 8, como elementos de lista, a partir de uma estrutura de repetição
do tipo while, em que o incremento da variável de controle ocorre ao final do loop. Já para a segunda coluna
temos uma estrutura do tipo for, com a variável de controle indo de 50 até 75, e a condicional permitindo
emitir apenas os valores em que ePrimo retorna true.

Vejamos o resultado da execução desse exemplo:

Execução de Exemplo010.html.

Tratamento de eventos
O conceito de eventos utiliza um conjunto de ações predeterminadas para as quais podemos dar uma
resposta programada ao chamador. No caso do HTML, o modelo de resposta parte dos atributos de evento
existentes nas tags HTML sendo relacionados com funções em Java Script.

Vejamos um tratamento de eventos, codificado a seguir como Exemplo011.html.

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 26/89
10/04/2023, 21:18 Camada de visão

A página contém apenas uma caixa de texto e um botão. Ao clicar sobre o botão, será apresentada uma
mensagem de boas-vindas. Note a utilização do método getElementById, ao nível do Java Script, para
capturar o elemento HTML a partir de seu identificador (id).

Criamos uma função, em Java Script, com o nome mostraMensagem, em que a caixa de texto é capturada
por meio do valor do atributo id, fornecendo o valor digitado para a variável nome, a partir de seu campo
value. Em seguida, ocorre a utilização da função alert, em que a mensagem será a concatenação da
expressão "Bem-vindo" com o nome digitado, causando a exibição de uma janela de diálogo simples,
apresentando as boas-vindas.

O método é associado ao clique do botão por meio do evento onclick, um dos atributos da tag. Vejamos o
resultado a seguir.

Execução de Exemplo011.html.

Notação JSON
Um elemento de grande relevância para a sintaxe do Java Script é a notação JSON (Java Script Object
Notation), que permite a definição de objetos de forma simples, além de ser o modelo padrão de dados para
Web Services do tipo RESTful. Um pequeno exemplo pode ser observado a seguir:

JSON
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 27/89
10/04/2023, 21:18 Camada de visão

Algo muito interessante no JSON é a simplicidade de escrita, com os atributos seguidos de seus valores,
segundo um padrão chave-valor. Essa simplicidade permite uma leitura natural dos objetos, o que justifica
sua ampla adoção para transmissão de dados na Web.

JQuery
Um framework Java Script que faz bom uso dos seletores CSS e notação JSON é o JQuery, algo que
justifica sua ampla utilização pelo mercado, com uma escrita simples e extensões muito abrangentes,
incluindo JQuery UI, que facilita a criação de interfaces com aspecto profissional e a definição de temas.

Vamos explorar as possibilidades do JQuery para a construção de interfaces, ou seja, trabalharemos com
temas e uso dos componentes JQuery UI. Começaremos baixando um tema adequado, a partir do endereço
https://jqueryui.com/themeroller, em que podemos escolher nossas configurações ou utilizar um tema da
galeria, clicando em download ao final.

Configuração para uso no JQuery UI.

Vamos utilizar o tema UI darkness. Após clicar em download, será aberta uma página, em que devemos
escolher a versão 1.13.1, para utilização com JQuery na versão 1.8 ou superior. Deixamos todas as opções
marcadas e clicamos no segundo botão de download, extraindo o conteúdo no diretório em que estão
nossas páginas HTML, ou na divisão Web Pages do projeto Web, no NetBeans, além de renomear o diretório
de base da biblioteca para jquery-ui.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 28/89
10/04/2023, 21:18 Camada de visão

Aplicação básica
Vamos criar o arquivo Exemplo012.html.

HTML
content_copy

Temos a inclusão das folhas de estilo e bibliotecas Java Script na divisão header, enquanto no corpo foi
definido apenas um componente de texto, identificado como dataCadastro. Também temos um pequeno
trecho em Java Script, criado segundo o padrão do JQuery, com a transformação do campo de texto em
calendário.

Para utilizar o JQuery em nossas páginas, deve ser definida uma função global. No corpo dela, trabalhamos
com os mesmos seletores adotados pelo CSS para obter os elementos da página, seguido da aplicação de
modificadores adequados, como datepicker, que transforma a entrada de texto em calendário interativo. O
resultado pode ser observado a seguir:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 29/89
10/04/2023, 21:18 Camada de visão

Calendário, criado com JQuery UI, no arquivo Exemplo012.html.

Diálogos modais e respostas a eventos


Vamos verificar a construção de diálogos modais e implementação da resposta a eventos, criando o arquivo
Exemplo013.html.

HTML
content_copy

No exemplo, temos uma página para definição de listas de tarefas, com a inclusão de tarefas na lista a partir
de um diálogo modal.

Vamos analisar o diálogo modal, que é construído sobre um elemento do tipo div, com o título "Definição de
Tarefas", contendo um formulário em seu interior. Para transformar o componente em um diálogo modal,
invocamos o modificador dialog, tendo como atributos: altura (height) de 200 pixels, largura (width) de 350
pixels, abertura automática (autoOpen) desativada e comportamento modal ativado.

O primeiro botão invocará a função criarTarefa, responsável pela adição de uma tarefa à lista, e o segundo
apenas provocará o fechamento do diálogo a partir de uma função anônima. Temos ainda o evento de
fechamento do diálogo (close), que limpa o campo de texto (edtTarefa) quando o diálogo é fechado,
fornecendo um texto vazio para val.

Comentário

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 30/89
10/04/2023, 21:18 Camada de visão

A criação da tarefa pode ser observada na função criarTarefa, em que temos a inclusão de um elemento do
tipo li à lista, identificada como listaTarefas, por meio do método append. Além da utilização de uma classe
CSS e de um estilo complementar para definição do espaçamento, modificando a aparência padrão do item
de lista, temos a captura do valor que foi digitado no campo de texto, por meio da val, para utilização no
item. Note que o fechamento do diálogo é invocado após o acréscimo da tarefa.

Segundo o comportamento padrão de um formulário, ocorreria o envio da informação com o


pressionamento da tecla "Enter". Para evitar que ocorra uma mudança de endereço, limpando os dados já
inseridos, buscamos (find) o form a partir de dlgTarefa, e associamos o evento de submit, em que
eliminamos o comportamento padrão (preventDefault) e fechamos o diálogo.

Note o uso do método on, que associa um evento de determinado tipo a uma função para o tratamento. A
mesma técnica foi adotada para a resposta ao clique no botão btnDialog, que efetua a abertura do diálogo
com a chamada do tipo open.

Para a lista, foi utilizado o modificador sortable, que permite arrastar os itens adicionados à lista,
modificando sua ordem de apresentação.

A interface criada pode ser observada a seguir:

Diálogo e lista ordenável, arquivo Exemplo013.html.

Chamadas assíncronas
Algo que se tornou muito comum nos sites atuais foi a utilização de chamadas assíncronas, segundo um
compêndio de tecnologias conhecido como AJAX. A biblioteca JQuery fornece um método muito simples
para efetuar chamadas desse tipo. Como o Java Script permite lidar com JSON de forma nativa, o
tratamento da resposta para Web Services RESTful não oferece qualquer tipo de dificuldade.

Para demonstrar o uso de AJAX, vamos criar o arquivo denominado Exemplo014.html.

LINGUAGEM DE PROGRAMAÇÃO UTILIZADA


content_copy
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 31/89
10/04/2023, 21:18 Camada de visão

Em termos de componentes HTML relevantes, temos apenas uma caixa de texto (edtNome), um botão
(btnEnviar) e uma divisão (listaDrinks). A divisão merece atenção especial, pois serve de base para um
componente accordion, o qual fornece a criação de áreas retráteis agrupadas, em que cada área receberá
um título, por meio da tag h3, e o conteúdo em uma div.

Temos a associação do clique ao botão, com uma função de tratamento que limpa o conteúdo interno de
listaDrinks, eliminando os resultados de consultas anteriores, formando o endereço de pesquisa,
concatenando o valor digitado em edtNome, e efetuando a chamada AJAX.

Como temos uma chamada assíncrona, é fornecido um objeto com o endereço (url) e a manipulação para
um retorno bem-sucedido (success), em que invocamos tratarDados com a passagem do retorno.

Comentário
O endereço é um serviço RESTful internacional para a consulta de receitas de drinks, que retorna diversas
informações no formato JSON. Como cada drink normalmente apresenta variações, teremos um vetor de
registros em que resgataremos os campos strDrink, strDrinkThumb e strInstructions, representando,
respectivamente, o nome, a foto e a receita do drink. Lembre-se de que as receitas estarão em inglês, mas a
tradução da página, por meio do navegador, apresentou ótimos resultados nos testes efetuados.

A função tratarDados recebe a resposta no formato JSON, e utiliza o operador forEach sobre o vetor drinks,
invocando adicionaLinha a cada registro, com a atualização do accordion, ao final, por meio da opção
refresh.

O formato de adicionaLinha é padronizado para o uso de forEach, com os parâmetros representando o


https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 32/89
10/04/2023, 21:18 Camada de visão

registro e o índice no vetor, em que item servirá de base para construir uma área de nosso accordion, com o
título (h3) associado a strDrink e o conteúdo (div) definido a partir de uma imagem apontando para
strDrinkThumb, ao lado do texto referente às instruções da receita (strInstructions). Vejamos o resultado:

Utilização de AJAX.

Existem muitos outros componentes disponíveis na biblioteca JQuery UI, inclusive opções para a criação de
menus, barras de progresso e abas de navegação.

video_library
Teoria na prática
Construção de páginas com JQuery UI.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 33/89
10/04/2023, 21:18 Camada de visão

Falta pouco para atingir seus objetivos.

Vamos praticar alguns conceitos?


Questão 1

Segundo as diretivas da W3C, enquanto o HTML fica com a responsabilidade de estruturar as páginas,
toda formatação visual deve ser implementada por meio de folhas de estilo. Mais do que formatações,

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 34/89
10/04/2023, 21:18 Camada de visão

o CSS permite controlar alguns comportamentos, como a mudança do aspecto do componente com a
passagem do mouse sobre ele, o que é feito com o qualificador

A empty.

B visited.

C focus.

D hover.

E active.

Parabéns! A alternativa D está correta.

Com o CSS, aplicamos formatações a elementos específicos da página, por meio de seletores, além de
permitir a definição de alguns comportamentos via qualificadores. Por exemplo, empty define a
aparência quando o componente não tem filhos, focus para aquele componente que detém o foco,
visited é utilizado nos links já visitados, active para o momento em que ocorre o clique, e hover para a
passagem do mouse sobre o componente.

Questão 2

O surgimento do JQuery, um framework construído totalmente em Java Script, trouxe novas


possibilidades para a criação de páginas para Web. Com uma sintaxe que alia os seletores CSS às
melhores práticas de programação em Java Script, permitiu a realização de tarefas que antes eram
consideradas trabalhosas com poucas linhas de código, além de oferecer diversos módulos que
expandem sua funcionalidade básica, como JQuery UI. Qual método do JQuery UI deve ser utilizado
para criar uma sequência de painéis, cada um com título e possibilidade de ocultação?

A dialog

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 35/89
10/04/2023, 21:18 Camada de visão

B slider

C accordion

D tooltip

E spinner

Parabéns! A alternativa C está correta.

Por meio do uso de accordion, conseguimos criar uma sequência de painéis, em que o título de cada
um é definido via tag h3 e o conteúdo em uma tag div, sendo o método aplicado a uma div que envolve
todos os pares h3/div. Por padrão, apenas um painel começa selecionado, ficando aberto (visível),
enquanto os demais apresentam apenas o título. O clique sobre o título de outro painel altera o painel
selecionado, ocultando o conteúdo dos demais.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 36/89
10/04/2023, 21:18 Camada de visão

2 - CRUD utilizando o framework Thymeleaf


Ao final deste módulo, você será capaz de aplicar o Thymeleaf por meio de
templates para definição da camada View do MVC.

Framework Thymeleaf
Por meio do framework Thymeleaf, criamos templates HTML, os quais promovem uma separação natural
da camada de visualização, definindo modelos que funcionam como protótipos de design naturais. Ele
trabalha com outros formatos, além do HTML, incluindo XML, texto e Java Script, de acordo com o modo de
operação utilizado. A principal diferença ocorre ao nível das críticas quanto à formação do arquivo ou tags
utilizadas.

Como podemos escolher entre diferentes dialetos, cada dialeto trará as regras de formação para o tipo de
arquivo e integração com os componentes naturais do ambiente, como os managed beans do ambiente
Java Web.

Camada model
Vamos criar um projeto do tipo Web Application, com gerenciamento pelo Maven, no NetBeans, como na
imagem a seguir. Nosso projeto terá o nome ExemploTh001, e o Group Id será com.universidade, utilizando
servidor Apache Tomcat, com Java EE versão 7.

Criação de aplicativo Web com gerenciamento do Maven.

Agora, vamos incluir a dependência do Thymeleaf no arquivo pom.xml, com o acréscimo do fragmento
apresentado a seguir:

HTML
content_copy
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 37/89
10/04/2023, 21:18 Camada de visão

O projeto deverá apresentar problemas com a adição da dependência, com um sinal de exclamação sobre o
ícone do projeto no navegador do NetBeans. Clique com o botão direito sobre o projeto e escolha a opção
"Resolve Project Problems".

Dica
A versão do JDK interferirá na utilização do Maven, sendo aconselhável adotar ao menos a plataforma 1.8,
que já traz o protocolo SSL atualizado.

Com o projeto configurado, vamos iniciar a codificação do aplicativo com a criação da classe Contato, no
pacote com.une sa.exemploth001.model.

JAVA
content_copy

No mesmo pacote, criaremos a classe ContatoRepositorio, simulando o acesso a uma base de dados, para
que possamos testar as interfaces gerenciadas pelo Thymeleaf.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 38/89
10/04/2023, 21:18 Camada de visão

JAVA
content_copy

As classes representam, respectivamente, uma entidade do sistema e o repositório para ela, em que o meio
de armazenamento é um HashMap estático. O repositório fornece métodos para incluir, excluir e obter a
lista de contatos, além de ser inicializada com dois contatos de exemplo.

Gerenciador para os modelos do Thymeleaf


Vamos definir um gerenciador para os modelos do Thymeleaf, com a criação da classe EngineFactory, no
pacote com.universidade.exemploth001.web.

JAVA
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 39/89
10/04/2023, 21:18 Camada de visão

A classe segue o padrão Factory, com apenas um método estático, para recebimento de um contexto Web
(ServletContext) e retorno de um gerenciador de templates. As configurações do gerenciador indicam o uso
de sintaxe HTML, com arquivos colocados no diretório templates de WEB-INF (prefixo), utilizando extensão
html (sufixo), além de adotar cache de uma hora.

Após a definição do objeto de configuração, o gerenciador (TemplateEngine) é instanciado e associado ao


configurador. Esse gerenciador será recebido por algum objeto capaz de tratar as requisições HTTP como
um filtro.

Comentário
Antes de chegar até o Servlet, a requisição passa pelos filtros de interceptação definidos, o que permite
automatizar ações como verificação de usuário e log de eventos.

Camada Controller
Antes de criar nosso filtro, vamos definir uma interface de comandos para nosso sistema, com o nome
IController, no pacote com.unesa.exemploth001.controller.

JAVA
content_copy

A interface criada definirá o modelo de chamadas da camada controller, utilizado nas ações do sistema,
cujas classes ficarão no mesmo pacote de IController. Começaremos definindo a classe ContatosList:

JAVA
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 40/89
10/04/2023, 21:18 Camada de visão

Vamos acrescentar a variável listaContatos, com a listagem de contatos obtida do repositório, para que seja
utilizada no template. Em seguida, ocorre o processamento para o template "contatos", utilizando o contexto
Thymeleaf (ctx) e a stream de saída para escrita do HTML (writer).

Definiremos procedimentos parecidos para as demais ações, como ContatosIncluir.

JAVA
content_copy

Aqui temos a ação de inclusão de contato, em que devemos obter os parâmetros enviados pela requisição
HTTP, criação de uma entidade a partir desses dados, e uso do repositório para a inclusão. O restante do
processo é equivalente ao da ação de listagem anterior.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 41/89
10/04/2023, 21:18 Camada de visão

Nada muito diferente ocorre para a ação de exclusão, que terá o nome ContatosExcluir.

Java
content_copy

Assim como na inclusão, após obter o nome enviado por meio da requisição e invocar a exclusão a partir do
repositório, configuramos os dados para exibição dos contatos.

Camada View
Temos o mesmo template para as três ações definidas. Para criá-lo, vamos adicionar uma página HTML
com o nome contatos, no diretório templates, a partir de WEB-INF, de acordo com código a seguir:

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 42/89
10/04/2023, 21:18 Camada de visão

Temos uma página HTML comum, com um formulário contendo dois campos e uma tabela, mas devemos
estar atentos ao uso de atributos definidos no namespace do Thymeleaf, que foi configurado ao nível da raiz
do documento, com o alias th. Serão esses atributos que sofrerão modificações pelo gerenciador de
templates durante o processamento.

Começando pela tabela, temos o comando th:each, que repetirá o trecho para cada elemento de
listaContatos, fornecida pelas ações, associando cada um à variável local contato. Em cada célula da linha,
teremos o valor preenchido, com o uso de th:text, a partir do campo específico de contato. Utilizamos ainda
o campo artificial contatoStat para colorização de linhas ímpares.

Comentário
Note o uso de cifrão ($) para acesso a um valor, colocado entre chaves. Também temos o uso de arroba (@),
executado localmente, o que foi utilizado na construção de um link dinâmico, com a passagem da rota e
seus parâmetros, colocados entre parênteses, definindo o endereço para exclusão de um registro
específico.

Quanto ao formulário, o único elemento relevante é o uso do atributo th:action, fornecendo a rota para
inclusão, em que o uso de arroba corrige eventuais modificações da URL.

Observamos que precisaremos do mapeamento de rotas para nossas ações, o que será feito pela classe
ControllerMappings, no pacote com.universidade.exemploth001.controller.

JAVA
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 43/89
10/04/2023, 21:18 Camada de visão

Nosso mapeamento foi definido com base em um HashMap, em que cada rota é associada a um
controlador para processamento da ação específica. A classe oferece apenas um método público, com o
nome fromPath, que recebe a rota e retorna o controlador correto.

Filtro de interceptação
Vamos definir o filtro de interceptação, com a criação da classe AppFilter, que ficará no pacote
com.universidade.exemploth001.web.

JAVA
content_copy

O mapeamento do filtro ocorre para qualquer rota iniciada com app, por meio da anotação WebFilter.
Detectada uma url com essas características, o fluxo é desviado para o método doFilter, em que é invocado
o método interno para processamento (process). O fluxo é devolvido para a cadeia de filtros quando o
método retorna false.

O processamento do filtro é iniciado com alguns testes para saber se existe uma classe de ação apropriada,

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 44/89
10/04/2023, 21:18 Camada de visão

retornando false quando um controlador não é encontrado. Caso seja encontrado, a resposta é iniciada com
a configuração do tipo de conteúdo e alguns cabeçalhos para impedir a utilização de cache no cliente.

Comentário
No passo seguinte, um objeto do tipo WebContext é instanciado, e o controlador que foi obtido
anteriormente processa a resposta, utilizando o objeto instanciado, o gerenciador de templates do filtro e o
escritor do canal de saída da resposta HTTP. Note que o gerenciador de templates é obtido no método init
do filtro, a partir de nossa classe EngineFactory.

Se o processamento não gerar falhas, o método retorna true ao chamador, mas se uma exceção ocorre, ela
é encapsulada em um ServletException, sendo ecoada para o contexto de execução com throw. Executando
o projeto, podemos acessar o endereço http://localhost:8080/app/contato/list, obtendo a saída a seguir:

Visualização da lista de contatos no projeto ExemploTh001.

Spring Boot com Thymeleaf

Criação do projeto
Embora seja possível utilizar o NetBeans para criação de aplicativos Spring Boot, com a simples alteração
do arquivo pom.xml em um aplicativo padrão Maven algumas plataformas tornam a tarefa mais simples.
Uma opção muito interessante é o Spring Tools Suite, baseado no Eclipse, que pode ser baixado a partir do
endereço https://spring.io/tools, com a instalação fornecida no formato de um arquivo jar executável, o qual
efetua uma simples extração de arquivos.

Para criar o projeto, escolha a opção de menu File, seguida de New e Spring Starter Project, adotando o
nome ExemploTh002, além do grupo com.universidade e pacote de mesmo nome, como pode ser
observado na imagem seguinte:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 45/89
10/04/2023, 21:18 Camada de visão

Criação de projeto Spring Boot no Spring Tools Suite.

Clicando no botão Next, devemos selecionar os pacotes do Spring que serão adicionados ao arquivo de
configuração pom.xml. Utilizaremos Spring Data JPA, H2 Database, Thymeleaf e Spring Web, como
observado a seguir:

Escolha dos pacotes utilizados no projeto.

Ao clicar em Finish, teremos um projeto Spring Boot com inclusão do Thymeleaf, modelo objeto-relacional
do JPA, arquitetura MVC do Spring Web e banco de dados do tipo H2, que trabalha em memória, eliminando
a necessidade de configurações. Para testar o projeto, vamos clicar com o botão direito sobre ele, no
Package Explorer, situado na divisão esquerda do ambiente, e escolher Run As, seguido de Spring Boot
App.

Poderemos observar as mensagens referentes à execução na divisão inferior, painel Console, na imagem
seguinte. Apesar de estar em execução, nosso sistema não tem rotas definidas, e a chamada ao endereço
de base (localhost:8080) retornará um erro.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 46/89
10/04/2023, 21:18 Camada de visão

Acompanhamento da execução no Console do Spring Tools Suite.

Controlador Spring Web


Vamos adicionar a classe HomeController ao pacote com.universidade, utilizando o botão direito sobre o
pacote e escolhendo New, seguido de Class.

JAVA
content_copy

Aqui definimos um controlador Spring Web, com a anotação Controller, tendo o mapeamento da raiz para o
método showHome, por meio da anotação GetMapping. No método, temos um parâmetro do tipo Model,
para a atribuição de valores que serão repassados para o template, e um retorno do tipo texto, que deverá
indicar o nome do template, sem a extensão HTML.

Configuração dos templates


No corpo do método, adicionamos o atributo data, com um objeto do tipo Date, e uma lista de valores texto
no atributo departamentos. Os valores serão enviados para o template home_tl, que deveremos criar no
diretório templates. Vejamos a estrutura de nosso projeto:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 47/89
10/04/2023, 21:18 Camada de visão

Estrutura do projeto ExemploTh002.

Para criar o arquivo, utilizamos o botão direito sobre o diretório templates, seguido de New e File, sendo
adotado o nome home_tl.html. A extensão deve ser digitada, e o conteúdo do novo arquivo é apresentado
na listagem seguinte.

HTML
content_copy

Aqui temos a criação de uma lista HTML, em que os elementos são obtidos por meio de th:each, a partir da
coleção departamentos, fornecida pelo controlador. Cada elemento é recuperado na variável departamento,
utilizada para substituir o conteúdo valor, com o uso de th:text. Da mesma forma, recuperamos a data para
preenchimento do elemento span.

Como os templates são estáticos, devemos parar a execução e reiniciar o servidor, o que é feito de forma
rápida pela opção relaunch, na barra de ferramentas da IDE, com um ícone mesclando os símbolos stop e
run. O resultado pode ser observado na imagem a seguir:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 48/89
10/04/2023, 21:18 Camada de visão

Visualização da página inicial com o template home_tl.html.

A sintaxe para configuração dos templates inclui muitas diretivas. Na tabela seguinte, temos os símbolos
utilizados pelo Thymeleaf, segundo a Standard Expression Syntax:

Símbolo Utilização

${...} Acessa o valor de uma variável, que pode ser local ou fornecida no Model.

*{...} Seleciona o campo de um objeto.

Recupera mensagens configuradas em um arquivo com extensão


#{...}
properties.

@{...} Transforma o endereço da rota em uma URL válida.

~{...} Insere o conteúdo de um fragmento HTML, viabilizando reuso no template.

Tabela: Símbolos utilizados na sintaxe do Thymeleaf.


Denis Cople.

Definição de mensagens
Para demonstrar o uso de mensagens, um recurso muito útil para a definição de mensagens padronizadas,
inclusive com suporte a idiomas, vamos criar o arquivo messages.properties no diretório resources, mesmo

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 49/89
10/04/2023, 21:18 Camada de visão

diretório de application.properties, com o conteúdo seguinte:

JAVA
content_copy

Em seguida, modificamos nosso arquivo de template (home_tl.html), alterando o trecho do título, conforme
apresentado a seguir:

HTML
content_copy

Ao executar novamente o servidor, nossa página apresentará o título definido no arquivo de propriedades, ou
seja, "Lista de Departamentos".

Aqui utilizamos o Spring Tools Suite por ser uma ferramenta mais prática para a criação dos aplicativos
Spring Boot, mas, se quiser utilizar o NetBeans, basta criar um projeto-padrão, com base no Maven, e alterar
o arquivo pom.xml, incluindo as dependências corretas, como o que é apresentado a seguir, extraído de
projeto exemplo:

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 50/89
10/04/2023, 21:18 Camada de visão

O exemplo demonstra a grande facilidade oferecida pelo Spring Boot, em conjunto com Thymeleaf, para a
criação de aplicativos.

Persistência e controle

Camada de persistência
Para criar nossa camada de persistência, vamos utilizar um banco de dados do tipo H2, que pode trabalhar
em memória, sem exigir configurações avançadas. Para acessar outros bancos, o arquivo
application.properties deverá ser alterado, incluindo as informações necessárias para conexão com o
banco de dados e gerenciamento de transações.

Já que estamos trabalhando no modelo MVC, nossas entidades e repositórios serão criados no pacote
com.universidade.model. Começaremos definindo uma entidade com o nome Departamento:

JAVA
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 51/89
10/04/2023, 21:18 Camada de visão

Nossa classe é uma entidade JPA, o que é estabelecido pela anotação Entity, sendo incluídos os campos
idDepto, chave primária com valor gerado automaticamente, e nome. Também temos um relacionamento de
um para muitos (OneToMany) com a entidade Funcionario, expresso por um conjunto (Set) de nome
funcionarios.

Precisamos, portanto, de uma segunda entidade, com o nome Funcionario:

JAVA
content_copy

Agora, temos os campos matricula, nome e dataCadastro, sendo matrícula a chave primária, além da
contraparte do relacionamento estabelecido anteriormente. Note o uso da anotação ManyToOne,
especificado como obrigatório, em um atributo de nome departamento, que é relacionado à propriedade
idDepto da entidade anterior (JoinColumn).

Cada uma das entidades precisará de um repositório JPA, que no Spring é definido por uma simples
interface, em que a comunicação com o banco é toda implementada pelo framework. Temos o conteúdo do
primeiro repositório apresentado a seguir:

JAVA
content_copy
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 52/89
10/04/2023, 21:18 Camada de visão

Definimos uma herança para a interface JpaRepository, com a especificação do tipo da entidade e de sua
chave primária. Ocorrerá o mesmo para o segundo repositório:

JAVA
content_copy

Camada de controle
Nossa camada model está completa e já podemos criar a classe DepartamentoController, no pacote
com.universidade.controller, representando nosso primeiro controlador.

JAVA
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 53/89
10/04/2023, 21:18 Camada de visão

Temos um controlador capaz de interceptar as rotas HTTP, por meio do mapeamento dos métodos pelas
anotações GetMapping e PostMapping. Temos ainda o relacionamento com um repositório, instanciado no
contexto do Spring por meio da anotação Autowired.

Comentário
O primeiro mapeamento ocorre para a rota /departamentos, em que o método de reposta adicionará uma
lista de departamentos aos dados da página, obtida pelo repositório por meio de findAll, retornando em
seguida o nome do template. Temos na rota /departamentos/excluir um comportamento muito similar, mas
ocorrendo a exclusão do departamento selecionado a partir de idDepto, com base no método deleteById do
repositório.

A inclusão utiliza a rota /departamentos/cadastro nos modos GET e POST, em que o modo GET associará
um atributo do tipo Departamento aos dados da página para cadastro, cujo nome é retornado ao final,
enquanto no modo POST recebemos os dados do formulário já preenchido em um parâmetro depto, do tipo
Departamento, anotado como ModelAttribute, procedendo com a persistência dos dados por meio do
método save do repositório, obtenção do conjunto de entidades atualizado via findAll, e retorno do template
para listagem.

Ainda não criamos nossos templates, mas a execução do aplicativo irá gerar as tabelas do banco H2, assim
como faria em qualquer outro banco, com a estrutura a seguir:

Estrutura do banco gerado pelo sistema.

Como o banco é recriado a cada execução, por estar trabalhando em memória, precisamos de alguns dados
de teste, o que será obtido com a execução de alguns comandos SQL. Teremos de adicionar um arquivo
com o nome import.sql, na raiz de resources, contendo a listagem a seguir, sem quebras de linha nos
comandos:

SQL
content_copy
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 54/89
10/04/2023, 21:18 Camada de visão

Algo interessante em nossa camada de controle é o fato de que o mesmo método utilizado para incluir um
registro permite também alterá-lo. Com base nessa característica, para adicionar a possibilidade de edição
no sistema, basta inserir um segundo mapeamento para a rota que inicia o template para preenchimento de
dados, mas com o acréscimo de um segmento com o identificador, permitindo fornecer os dados atuais da
entidade.

O método adicionado pode ser observado na listagem seguinte, para a classe DepartamentoController:

JAVA
content_copy

O mesmo tipo de modificação pode ser efetuado em FuncionarioController, adicionando o método


apresentado a seguir. Note que, em ambos os casos, temos a definição da variável que receberá o
segmento com a anotação PathVariable:

JAVA
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 55/89
10/04/2023, 21:18 Camada de visão

Com as camadas de persistência e controle prontas, podemos iniciar a construção da camada de


visualização, ou seja, dos templates. Vejamos a estrutura de projeto até o momento:

Projeto com as camadas de controle e persistência.

Interface do CRUD

Templates para departamentos


Agora, vamos criar nossa camada de visualização, que será constituída pelos templates requeridos na
camada de controle, com o nome definido a partir do retorno de cada método. Todos os arquivos serão
criados no diretório templates, a partir de resources, com o clique do botão direito sobre o diretório e
escolha da opção New, seguida de File.

Nosso primeiro template será definido no arquivo deptolist.hmtl.

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 56/89
10/04/2023, 21:18 Camada de visão

Temos a definição de um link para inclusão de departamentos, com uso de arroba e indicação da rota
/departamento/cadastro no atributo th:href, seguido da definição de uma tabela para exibição dos dados.
Na tabela, teremos outros links para exclusão e alteração de um departamento. A exclusão utiliza a sintaxe
para uso de parâmetros na requisição, enquanto a alteração trabalha com fornecimento da chave em um
segmento da rota.

Por meio de th:each, recuperamos os departamentos que foram enviados pelo controlador, obtendo cada
um deles na variável depto, e utilizamos cada ocorrência para a construção de uma linha da tabela. Os
valores de cada campo da entidade são acessados com o uso de cifrão, utilizado tanto para o
preenchimento das células de valores quanto na definição dos links de forma dinâmica.

Já podemos executar o aplicativo e acessar o endereço http://localhost:8080/departamentos, obtendo a


saída a seguir:

Listagem dos departamentos .

Agora, vamos definir o segundo template, com o nome deptodata.html.

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 57/89
10/04/2023, 21:18 Camada de visão

Nosso formulário utilizará o objeto depto, fornecido pelo controlador, por meio de th:object, e iniciará a ação
definida por th:action para a rota /departamentos/cadastro, no modo POST. Observe a utilização de
asterisco para acesso aos campos do objeto, com base em th:field, em cada um dos campos de nosso
formulário.

Como a chave primária é gerada automaticamente para o departamento, ela é colocada em um campo
escondido (hidden), evitando a edição pelo usuário. Já o campo referente ao nome será apresentado em
branco para a inclusão, ou com o valor corrente na alteração.

Já podemos acessar os diversos links oferecidos pela tela de listagem, pois o controlador está preparado
para todas as rotas solicitadas. Clicando na opção "Novo Departamento", abriremos o formulário de dados
em branco.

Formulário para inclusão e alteração de departamento.

Templates para funcionários


Vamos definir as telas para funcionários, iniciando com o arquivo funclist.html.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 58/89
10/04/2023, 21:18 Camada de visão

HTML
content_copy

Há muita similaridade com a tela de listagem de departamentos, agora com as rotas iniciadas por
/funcionários, mas temos algumas pequenas novidades. Note o uso da macro, precedida por cerquilha,
com o nome dates.format, que permite formatar a data de cadastro, bem como o acesso ao nome do
departamento de forma direta, a partir do atributo de relacionamento existente na classe Funcionario.

Acessando o endereço http://localhost:8080/funcionarios, podemos testar a tela, obtendo a saída a seguir:

Listagem de funcionários.

O formulário para funcionários será definido no template funcdata.html.

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 59/89
10/04/2023, 21:18 Camada de visão

Nesse caso, temos a chave primária digitada pelo usuário. Há também a definição de um campo de seleção
para o campo departamento, em que as opções são preenchidas a partir da lista de departamentos com o
nome deptos, fornecida pelo controlador. Observe a utilização de th:each, para a iteração, th:value, para
definição do valor fornecido pela opção, e th:text, para o texto apresentado.

Com o template criado, acessando os links para alteração ou inclusão, teremos a exibição da tela a seguir:

Formulário para inclusão e alteração de funcionário.

video_library
Teoria na prática
Utilizando Thymeleaf com Spring Boot

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 60/89
10/04/2023, 21:18 Camada de visão

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 61/89
10/04/2023, 21:18 Camada de visão

Falta pouco para atingir seus objetivos.

Vamos praticar alguns conceitos?


Questão 1

As diretivas utilizadas no Thymeleaf permitem uma integração muito simples entre o template HTML e
o contexto do framework Spring, possibilitando recuperação de valores e reutilização de fragmentos,
entre diversas outras possibilidades. Se quisermos recuperar o nome da empresa a partir de um
parâmetro global, para que seja apresentado em cada página, qual símbolo seria utilizado pela diretiva
de recuperação?

A Arroba

B Cifrão

C Til

D Asterisco

E Cerquilha

Parabéns! A alternativa E está correta.

Segundo a Standard Expression Syntax, o uso de cerquilha (#) permite recuperar textos padronizados a
partir de arquivos de propriedades, particularmente com a definição de um arquivo message.properties,

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 62/89
10/04/2023, 21:18 Camada de visão

no diretório resources, em que serão colocadas as mensagens do sistema, como pares de chave e
valor, com a recuperação posterior a partir da chave.

Questão 2

Os templates do Thymeleaf utilizam atributos nas tags HTML, definidos em seu namespace, para definir
ações diversas, como controle de visibilidade e substituição de conteúdo para a tag, sendo
normalmente adotado o prefixo th. Se quisermos repetir determinado trecho, para todos os elementos
de uma coleção, qual seria o atributo adotado na tag principal do trecho?

A Th:each

B Th:text

C Th:object

D Th:action

E Th:value

Parabéns! A alternativa A está correta.

A utilização de th:each permite repetir a tag e seu conteúdo interno, ou seja, o trecho da página, para
cada objeto da coleção. Em termos práticos, recuperamos uma coleção enviada pelo controlador,
precedida de cifrão, atribuindo a um objeto em cada iteração. O objeto pode ser acessado no conteúdo
interno, recuperando suas propriedades. Um exemplo de utilização desse controle de fluxo seria
th:each="depto: $$ {deptos}".

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 63/89
10/04/2023, 21:18 Camada de visão

3 - Estudo de caso com Framework


Bootstrap
Ao final deste módulo, você será capaz de empregar o Bootstrap na
construção da interface para garantia de produtividade.

Framework do Bootstrap
O framework Bootstrap permite a definição de interfaces muito agradáveis, com uma estética alinhada aos
padrões de mercado, além de trazer elementos que garantem a responsividade, ou seja, adapta-se a
diferentes plataformas de forma natural. Com o Bootstrap, obtemos um conjunto de componentes
responsivos, com visual moderno, perfeitamente alinhados aos padrões estabelecidos no mercado.

O Bootstrap encapsula o framework JQuery, adicionando diversas funcionalidades por meio de classes CSS.
Podemos baixar o framework no endereço https://getbootstrap.com/. Além de oferecer diversas opções de
formatação para componentes, como botões e caixas de texto, temos a definição de contêineres, muito
úteis para a organização da tela.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 64/89
10/04/2023, 21:18 Camada de visão

Estilos de botões
Para compreender a utilização do Bootstrap, vamos criar o arquivo Exemplo015.html, em um projeto Web
do NetBeans, dando continuidade aos exemplos iniciais do conteúdo.

HTML
content_copy

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Exemplo015</title>
5 <meta charset="utf-8">
6 <meta name="viewport" content="width=device-width, initial-scale=1">
7
8 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.c
9 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundl
10
11 </head>
12 <body>
13 <div class="container">
14 <h2>Estilos de Botões</h2>

No cabeçalho do arquivo, temos as importações necessárias para uso do Bootstrap, ou seja, a folha de
estilo bootstrap.min.css e o script bootstrap.bundle.min.js, ambos obtidos a partir do repositório npm, na
versão 5.0.2. Todos os arquivos que utilizarem o framework deverão ter as mesmas importações de nosso
exemplo.

Podemos observar a definição da área principal do aplicativo, com a classe container, e diferentes
formatações para os botões, com a classe btn, que pode ser especializada para suas subclasses, como btn-
success e btn-info, modificando o aspecto dos botões, segundo padrões adotados nas diferentes
plataformas, particularmente Web e móvel.

Abrindo a página em um navegador, teremos o seguinte resultado:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 65/89
10/04/2023, 21:18 Camada de visão

Botões formatados pelas classes do Bootstrap.

Caixas de diálogo modais


O uso de caixas de diálogo modais permite uma comunicação simples e organizada com o usuário. Vamos
explorar essa funcionalidade no arquivo Exemplo016.html.

HTML
content_copy

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Exemplo016</title>
5 <meta charset="utf-8">
6 <meta name="viewport" content="width=device-width, initial-scale=1">
7
8 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.c
9 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundl
10
11 </head>
12 <body>
13 <div class="container">
14 <h2>Exemplo de Modal</h2>

Na primeira parte do código, temos um botão, configurado com o aspecto btn-danger, e dois atributos
especiais, data-bs-toggle e data-bs-target: o primeiro define que será alterada a visibilidade de um
elemento modal, e o segundo indica o modal a partir do id. Em seguida, temos a construção do modal em si,
com id myModal, por meio de tags div.

Comentário

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 66/89
10/04/2023, 21:18 Camada de visão

A divisão de nível mais alto do diálogo é configurada com as classes modal e fade, além de usar um atributo
role, com valor dialog, o que indica uma caixa de diálogo. Em seguida, temos um segundo nível, configurado
como modal-dialog, e um terceiro, do tipo modal-content, que será responsável pelo conteúdo interno da
caixa de diálogo.

O conteúdo do diálogo é composto de três áreas, configuradas como modal-header, para as informações de
título, modal-body, para as informações que serão exibidas, e modal-footer, para a parte inferior do diálogo,
normalmente com alguns botões de resposta.

Os dois botões são configurados para o fechamento do diálogo, por meio do atributo data-bs-dismiss,
utilizando o valor modal. O primeiro é o botão de fechamento padrão para janelas, posicionado no canto
superior direito, e o segundo, um botão padrão, colocado na parte inferior. Podemos observar nosso diálogo
sendo ativado:

Diálogo modal com Bootstrap.

Sistema de Grid
O sistema de grid do Bootstrap é outro elemento importante, utilizado na organização da tela a partir de
divisões. Ele segmenta a tela em até 12 colunas, que podem ser combinadas, como na listagem seguinte,
que deverá ficar no arquivo Exemplo017.html.

HTML
content_copy

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Exemplo017</title>
5 <meta charset="utf-8">
6 <meta name="viewport" content="width=device-width, initial-scale=1">
7 <style> div {border: black dashed thin} </style>
8
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 67/89
10/04/2023, 21:18 Camada de visão

9 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.c
10 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundl
11
12 </head>
13 <body>
14 <div class="container-fluid">

Temos a primeira linha (row) com duas células de uma coluna (col-sm-1), uma célula de duas colunas (col-
sm-2) e duas de quatro colunas (col-sm-4), a segunda linha com uma célula de quatro colunas e uma de
oito colunas (col-sm-8), e apenas uma célula de 12 colunas (col-sm-12) na terceira linha. O resultado pode
ser observado a seguir:

Organização da página pelo sistema de grid.

Componentes para navegação


Os componentes nav e navbar permitem a construção simples de menus para o sistema. Vamos adicionar o
arquivo Exemplo018.html, com o conteúdo a seguir:

HTML
content_copy

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Exemplo018</title>
5 <meta charset="utf-8">
6 <meta name="viewport" content="width=device-width, initial-scale=1">
7
8 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.c
9 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundl
10

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 68/89
10/04/2023, 21:18 Camada de visão

11 </head>
12 <body>
13 <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
14

A barra de navegação do exemplo poderia ser utilizada como menu principal do sistema, pois viabiliza
mudança de páginas e indicação da opção corrente de forma automática. Definimos o componente de
navegação no nível mais alto, utilizando fundo escuro (navbar-dark e bg-dark), além do preenchimento
horizontal (navbar-expand-lg).

O conteúdo do menu é divido em três colunas, segundo os valores de grid do Bootstrap. A primeira contém
a opção principal do menu (navbar-brand), e a última, um botão comum, no estilo btn-danger. Na coluna do
meio, temos uma lista, configurada como navbar-nav, em que cada item é uma opção de navegação (nav-
item) contendo um link (nav-link), sendo a opção corrente configurada no link por meio da classe active.

A execução do exemplo gerará o seguinte resultado:

Menu de navegação criado com NavBar.

Uso de Bootstrap com Thymeleaf

Definição do menu
Utilizar o framework Bootstrap sob o Thymeleaf é uma tarefa simples, pois não requer grandes
modificações nos templates HTML. Nossa preocupação inicial será apenas a inclusão de uma dependência
no arquivo pom.xml, como no fragmento a seguir:

Arquivo De Configuração
content_copy
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 69/89
10/04/2023, 21:18 Camada de visão

Os elementos WebJars são as bibliotecas do Bootstrap oferecidas no formato jar, para permitir a utilização
ao nível do projeto, sem a necessidade de acesso ao repositório remoto. Aqui foi escolhida a versão 5.0.2,
devido à existência de documentação mais completa.

Vamos acrescentar a página menu.html no projeto ExemploTh002, nosso exemplo de CRUD, no diretório
templates, como as demais páginas, utilizando o conteúdo a seguir:

HTML
content_copy

O código utilizado é apenas uma adaptação de nosso menu anterior, mas, agora, com indicação real de
navegação. Esse template será incluído em todas as páginas, aproveitando o recurso de fragmentos
oferecido pelo Thymeleaf.

No primeiro nível, temos a definição do nome do fragmento como


menuprincipal, por meio do atributo th:fragmente. Todos os endereços
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 70/89
10/04/2023, 21:18 Camada de visão

dos links passam a apontar para as rotas de nosso sistema, sempre por
meio do atributo th:href, com a utilização de arroba para correção.

Temos ainda a indicação da opção ativa com uma inclusão condicional de classe, efetuada no atributo
th:classappend, com base em uma condição na qual o estilo active será utilizado apenas quando a variável
pagina tiver o valor equivalente ao do teste.

Navegação utilizando o menu


Agora, vamos definir uma nova página inicial, com o nome home.html, no diretório templates, de acordo
com a listagem seguinte:

HTML
content_copy

Nosso novo template inclui os arquivos CSS e JS necessários para o Bootstrap, no cabeçalho, sempre com
a utilização do Thymeleaf para a correção dos endereços.

A utilização do fragmento ocorre imediatamente no início do corpo da página, com uma div que tem o
conteúdo substituído, por meio do atributo th:replace, em que indicamos o template (menu) e o nome do
fragmento (menuprincipal). Note a utilização de til para uso do fragmento, bem como a passagem da
variável pagina na chamada, que, nesse caso, estará em branco, pois não se trata de nenhuma das opções
de cadastro.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 71/89
10/04/2023, 21:18 Camada de visão

Agora, vamos modificar a classe HomeController, criada anteriormente, para que utilize o novo template na
rota referente à raiz. Vamos utilizar o código apresentado a seguir, mantendo a chamada do exemplo antigo
na rota /old:

JAVA
content_copy

Neste ponto, é possível navegar para as páginas de cadastro, mas sem a possibilidade de usar o menu para
retornar porque não foi incluído nos templates. Precisamos alterar os templates para inclusão do menu, o
que é feito por meio da adição das importações do Bootstrap no final do cabeçalho, e inclusão do fragmento
imediatamente no início do corpo da página.

O trecho de código apresentado a seguir mostra a modificação que precisa ser efetuada nos templates
deptolist e deptodata, de forma semelhante à página inicial, mas, agora, utilizando o valor "departamentos"
para a variável do fragmento:

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 72/89
10/04/2023, 21:18 Camada de visão

Executando novamente o aplicativo, teremos acesso às páginas de departamento com exibição do menu,
tanto para a listagem quanto para o cadastro, e poderemos retornar para a listagem rapidamente com o
clique sobre a opção de menu. Também teremos a indicação da opção de cadastro em uso, com fonte mais
clara, como podemos observar na imagem seguinte:

Listagem de departamentos com inclusão do menu.

O mesmo procedimento deve ser feito para os templates funcdata e funclist, mas, agora, com a utilização
do valor "funcionarios" na variável do fragmento:

HTML
content_copy

Alteração das interfaces do CRUD


https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 73/89
10/04/2023, 21:18 Camada de visão

Templates com listas


Nossa interface está funcional, mas ainda muito simples, o que ajustaremos com a utilização das classes
do Bootstrap. Vamos começar alterando o template deptolist:

LINGUAGEM DE PROGRAMAÇÃO UTILIZADA


content_copy

Definimos as classes de botão para os links e a formatação da tabela, em que foram utilizadas as classes
table e table-striped, para expandir o conteúdo na largura da página e trabalhar com alternância de fundo
nas linhas. Temos uma classe col-sm-2, aplicada às células com os links de alteração e exclusão, para que
não utilizem um espaçamento maior do que o necessário.

Todos os links receberam a classe btn, sendo adotado btn-danger para exclusão, e btn-primary para
inclusão e alteração, além da adoção de tamanho pequeno para os botões de alteração e exclusão, por meio
da classe btn-sm. O resultado é apresentado a seguir:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 74/89
10/04/2023, 21:18 Camada de visão

Listagem de departamentos formatada com Bootstrap.

O mesmo tipo de alteração deverá ser efetuado no template funclist.

LINGUAGEM DE PROGRAMAÇÃO UTILIZADA


content_copy

O resultado das alterações efetuadas pode ser observado na imagem seguinte, obtida durante a execução
do sistema:

Listagem de funcionários formatada com Bootstrap.

Templates de cadastros
Podemos modificar os formulários do sistema, a começar pelo template deptodata.

LINGUAGEM DE PROGRAMAÇÃO UTILIZADA


content_copy
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 75/89
10/04/2023, 21:18 Camada de visão

As alterações efetuadas foram mínimas, incluindo o encapsulamento do conteúdo original em uma div com
a classe container, e o uso das classes btn e btn-primary no botão de envio. Quanto aos componentes de
entrada, cada conjunto formado por label e input é colocado em uma div do tipo form-group, além do uso da
classe form-control no input e form-label no label, o que traz, além de boa organização, alguns efeitos
visuais no ganho de foco.

O resultado das mudanças pode ser observado a seguir:

Formulário de departamento formatado com Bootstrap.

Alterações semelhantes precisam ser efetuadas no template funcdata.

LINGUAGEM DE PROGRAMAÇÃO UTILIZADA


content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 76/89
10/04/2023, 21:18 Camada de visão

A presença de uma caixa de seleção levou à adoção da classe form-select. Vejamos o resultado das
modificações:

Formulário de funcionário formatado com Bootstrap.

Tratamento de erros
Em muitas situações, você deve ter tentado excluir um departamento e ocorreu um erro, o que normalmente
é causado pela quebra da integridade referencial, imposta pelo relacionamento de um para muitos. É
interessante informar o erro ao usuário de forma adequada, utilizando mensagens claras. Faremos isso
aproveitando nossa tela inicial, no template home, de acordo com a listagem seguinte:

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 77/89
10/04/2023, 21:18 Camada de visão

Tudo que fizemos foi acrescentar uma div com a classe container, no primeiro nível, e uma div interna com
as classes alert e alert-danger, que será responsável por emitir um alerta, na tela principal, com a
mensagem de erro. O texto da mensagem é preenchido pelo atributo th:text, mas será exibido apenas se um
objeto de mensagem for enviado a partir do controlador, com base na condição utilizada no atributo th:if.

Precisamos alterar o método excluir, em DepartamentoController, para o tratamento de erros na utilização


da rota /departamentos/excluir.

JAVA
content_copy

Execute novamente o aplicativo e tente remover um departamento que tenha funcionários, o que fará exibir
a mensagem enviada a partir do tratamento da exceção pelo controlador, como observado a seguir:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 78/89
10/04/2023, 21:18 Camada de visão

Mensagem de erro exibida na tela principal.

Acréscimo de autenticação no aplicativo

Configuração da autenticação
Nosso aplicativo está totalmente funcional, mas seria interessante acrescentar algum modelo de
autenticação. Não trabalharemos com um padrão robusto, mas apenas com um exemplo simples, adotando
usuário fixo no controlador de autenticação, o que não impedirá a utilização de todo o fluxo de execução,
com os componentes associados e a integração com Thymeleaf.

Inicialmente, vamos acrescentar a dependência para o Spring Security no arquivo pom.xml.

Arquivo De Configuração
content_copy

Tentando executar novamente o aplicativo, será exibida a tela de login, impedindo a utilização do sistema,
pois a autenticação não está configurada. Precisamos configurá-la criando a classe AuthController, no
pacote com.universidade.

Java
content_copy
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 79/89
10/04/2023, 21:18 Camada de visão

As anotações Configuration e EnableWebSecurity integram nossa classe ao contexto do Spring, definindo-a


como controladora de segurança-padrão. Ainda em termos da integração, temos dois beans: um para
gerência da criptografia (passwordEncoder), que utiliza algoritmo BCrypt, e outro para a base de usuários
(userDetailsService), em que é criado apenas um usuário, com login usu1 e senha 1234, o qual é anexado
ao gestor em memória.

Atenção!
No método configure, tendo como parâmetro um objeto do tipo HttpSecurity, efetuamos todo o controle de
autenticação, com bloqueio por padrão, mas liberando as rotas para a raiz e para o login. Outro elemento
configurado é o modelo utilizado para o login, que, no caso, será feito a partir de um formulário (formLogin),
além do redirecionamento do logout para a página inicial, por meio de logoutSuccessUrl, impedindo que
seja solicitado um novo login de imediato.

O segundo método configure, com parâmetro do tipo WebSecurity, é necessário para garantir a
funcionalidade do Bootstrap, mesmo que o usuário não esteja autenticado. Para tal, usamos a diretiva
ignoring, aplicada a toda rota partindo de webjars.

Já podemos executar nosso projeto e verificar como o login é solicitado quando acessamos o cadastro de
departamentos ou o de funcionários. Nosso próximo passo será implementar o logout, com a modificação
do template menu, apenas no trecho em que encontramos o botão de saída do sistema, conforme o
fragmento de código apresentado a seguir:

HTML
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 80/89
10/04/2023, 21:18 Camada de visão

Trocamos o botão por um link, apontando para a rota logout, e permitimos sua visualização apenas quando
há um usuário logado, o que é feito com o teste isAuthenticated, no atributo sec:authorize. Apenas com a
utilização dos extras do Thymeleaf para integração com Spring Security, incluídos nas dependências do
projeto, foi possível utilizar o dialeto específico voltado para a segurança.

Personalização das telas de login e logout


Como passo final, vamos personalizar a tela de login para que fique integrada ao ambiente de nosso
sistema. Começamos com a criação de um template com o nome login.html.

HTML
content_copy

Por se tratar de uma personalização, devemos manter a chamada do formulário e o nome de cada campo.
No caso, os campos são username e password, com envio de informação para /login, no modo POST.
Temos ainda uma div configurada como alert-danger para avisar que os valores utilizados são inválidos, a
https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 81/89
10/04/2023, 21:18 Camada de visão

qual é ativada apenas quando existe param.error fornecido pelo controlador do Spring Security.

Todas as demais configurações utilizadas são semelhantes às que foram adotadas nas demais páginas do
sistema. Podemos observar a aparência da nova tela de login a seguir:

Login personalizado no sistema.

Precisamos também de um template com o nome logout.html para a confirmação da saída.

LINGUAGEM DE PROGRAMAÇÃO UTILIZADA


content_copy

Novamente, temos que nos integrar ao comportamento do framework. Tudo de que precisamos é uma
chamada para a rota /logout em modo POST. Nossa janela apenas apresenta um título, mensagem para o
usuário, e botão do tipo btn-danger, para efetivar o logout, como podemos observar a seguir:

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 82/89
10/04/2023, 21:18 Camada de visão

Confirmação de logout personalizada no sistema.

Para que as personalizações sejam efetivadas, precisamos adicionar dois mapeamentos em modo GET na
classe HomeController.

JAVA
content_copy

As rotas chamadas no modo GET direcionarão para nossos templates, enquanto o modo POST é
interceptado pelo Spring Security, mantendo todo o arcabouço de autenticação.

Precisamos alterar o método configure, com parâmetro do tipo HttpSecurity, em nossa classe
AuthController, responsável pela autenticação dos usuários, de acordo com o fragmento de código
apresentado a seguir. Note que incluímos apenas os elementos necessários para indicar as rotas para o
login (loginPage) e para o logout (logoutUrl):

JAVA
content_copy

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 83/89
10/04/2023, 21:18 Camada de visão

Ao trabalhar com modelos mais robustos de autenticação, podem ser necessárias alterações no arquivo
application.properties, bem como no acesso a bancos de dados externos.

video_library
Teoria na prática
Construção de Menus com Bootstrap.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 84/89
10/04/2023, 21:18 Camada de visão

Falta pouco para atingir seus objetivos.

Vamos praticar alguns conceitos?


Questão 1

O framework Bootstrap viabiliza a construção de interfaces responsivas, alinhadas com os melhores


padrões de design, de forma extremamente simples, com base em classes CSS, o que permite,
inclusive, a escolha de temas personalizados para cada empresa. Por exemplo, se nosso sistema
pergunta, em uma caixa de diálogo, se desejamos excluir todos os registros, qual seria a classe CSS
correta para o botão de confirmação?

A btn-primary

B btn-success

C btn-info

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 85/89
10/04/2023, 21:18 Camada de visão

D btn-danger

E btn-link

Parabéns! A alternativa D está correta.

As classes específicas para botões apresentam cores e formatos padronizados para cada ambiente de
execução quando adotamos o Bootstrap. Quanto ao exemplo de nosso sistema, a exclusão de todos os
registros de uma base é sempre uma operação perigosa, que exige plena atenção do usuário na
confirmação, o que levará à adoção da classe btn-danger, como em < button class=".btn .btn-danger" >
Confirmar < /button >, causando a utilização da cor vermelha, normalmente associada ao perigo.

Questão 2

Uma caraterística muito interessante do Thymeleaf é sua fácil integração com o modelo de segurança
do Spring, com base no Spring Security, o que permite a definição de templates com o controle da
disponibilidade de elementos para perfis específicos de usuários, ou simplesmente a alternância da
visibilidade de algum trecho quando ocorre autenticação. Para o segundo caso, qual método retorna ao
estado atual da autenticação?

A isLogged

B isAuthorized

C isAuthenticated

D isCertified

E isOpened

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 86/89
10/04/2023, 21:18 Camada de visão

Parabéns! A alternativa C está correta.

Para integrar o Thymeleaf com Spring Security precisamos apenas acrescentar a dependência
thymeleaf-extras-springsecurity na versão utilizada pelo projeto. Com o acréscimo dessa dependência,
o prefixo sec (Security) fica disponível para uso nos atributos das tags, com acesso aos mecanismos
de segurança do ambiente.

O método isAuthenticated retorna true para um usuário autenticado. Logo, a visibilidade do


componente pode ser alternada facilmente, com o acréscimo do atributo
sec:authorize="isAuthenticated()".

Considerações finais
De forma geral, pessoas têm competências diferentes. Muitos programadores não apresentam habilidade
para a construção de interfaces de usuário complexas, algo que é uma característica dos designers.
Entretanto, com a alta padronização das interfaces atuais, surgiram ferramentas que viabilizam a
construção de interfaces de alta qualidade com baixo esforço.

Mesmo com a disponibilidade dessas ferramentas, o conhecimento dos princípios elementares para a
construção de páginas é necessário, principalmente para sua organização estrutural. É preciso conhecer
sintaxes como HTML, Java Script e CSS, além de frameworks comuns no mercado, como JQuery UI.

Após a compreensão dos princípios para a construção das páginas, precisamos integrá-las com os
componentes da camada Controller, dentro de uma arquitetura MVC. O uso de Thymeleaf nos proporcionou
essa integração de forma natural, com base em templates HTML, que podem ser manipulados por
designers, por meio de ferramentas de edição apropriadas.

Com as interfaces integradas, os sistemas garantem as funcionalidades definidas nos requisitos, mas o
mercado exige características como responsividade e padronização no design das páginas. O Bootstrap
permite o acréscimo dessas características de forma não invasiva, por meio de classes para estilização,
garantindo qualidade e produtividade necessárias.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 87/89
10/04/2023, 21:18 Camada de visão

headset
Construção da camada View
Para encerrar, ouça sobre processo de criação para páginas HTML, bem como a integração com a camada
de controle de um sistema Spring Web por meio do Thymeleaf.

Referências
BOAGLIO, F. Spring Boot. 1. ed. São Paulo: Casa do Código, 2017.

BURKE, B; MONSON, R. Enterprise Java Beans 3.0. 5. ed. São Paulo: Pearson, 2007.

DEBLAUWE, W. Taming Thymeleaf. 1. ed. USA: Lulu Press, 2021.

DEITEL, H; DEITEL, P. Java, Como Programar. 10. ed. São Paulo: Pearson, 2016.

HORSTMANN, C. Modern Java Script For The Impatient. 1. ed. USA: Addison-Wesley, 2020.

MAZZA, L. HTML5 e CSS3. 1. ed. São Paulo: Casa do Código, 2014.

PATEL, N. Spring 5.0 Projects. 1. ed. Reino Unido: Packt Publishing, 2019.

SOUZA, N. Bootstrap 4. 1. ed. São Paulo: Casa do Código, 2018.

SPILCA, L. Spring Security In Action. 1. ed. USA: Manning, 2020.

TURNQUIST, G. Learning Spring Boot 2.0. 2. ed. Reino Unido: Packt Publishing, 2017.

ZAKAS, N. High Performance Java Script. 1. ed. USA: O'Reilly, 2010.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 88/89
10/04/2023, 21:18 Camada de visão

Explore +
Acesse o guia CSS Tutorial, disponibilizado pela W3Schools, e navegue pelas opções do menu, no lado
esquerdo da página, para aprender tudo que é necessário sobre CSS.

Explore os diversos exemplos disponibilizados pelo JQuery UI (jqueryui.com), navegando pelas opções do
menu lateral esquerdo e utilizando a opção "view source" para conferir os códigos.

Confira o guia Bootstrap 5 Tutorial - An Ultimate Guide for Beginners e navegue pelas opções do menu
lateral esquerdo para aprender a utilizar o Bootstrap com base em exemplos.

Leia o artigo Working with Fragments in Thymeleaf, oferecido pelo Baeldung, e compreenda melhor a
utilização de fragmentos no Thymeleaf.

Leia o artigo Use Thymeleaf Templates with Spring WebFlux to Secure Your Apps, de Jimena Garbarino,
descrevendo a autenticação em arquitetura de fluxo com Spring e Thymeleaf.

https://stecine.azureedge.net/repositorio/00212ti/03593/index.html# 89/89

Você também pode gostar