Programação para Web 3

Templates com FreeMarker

Prof. Me. Danilo Bueno

Agenda

  1. O problema da concatenação
  2. Motores de template
  3. O FreeMarker
  4. Construindo o cardápio, passo a passo
  5. Reaproveitando templates

O problema

HTML montado em Java

String html = "<h1>Cardápio</h1><ul>";for (String item : itens) {    html += "<li>" + item + "</li>";}html += "</ul>";
  • Sem destaque de sintaxe para o HTML
  • Tag esquecida só quebra em execução
  • Mistura lógica de negócio e apresentação

Motores de template

Definição de motor de template

  • Programa que combina um template (estrutura fixa) com dados (variáveis) para gerar um documento final
  • O princípio não é exclusivo da Web: a mesma ideia aparece em mala direta e em geração automática de contratos e relatórios
  • No servidor, o motor gera o HTML antes de a resposta ser enviada

O navegador nunca vê a marcação do template, só recebe o HTML já pronto.

Onde aparecem motores de template

Ecossistema Motores comuns
Java JSP, FreeMarker, Thymeleaf
Python Jinja2, Django Templates
PHP Blade (Laravel), Twig (Symfony)
JavaScript Handlebars, EJS, Pug
Ruby ERB

O mesmo padrão se repete em praticamente toda linguagem usada no servidor.

Duas filosofias de template

  • Sem lógica (logic-less): só substitui variáveis, sem laços nem condicionais no template (ex.: Mustache); toda decisão fica no código
  • Com diretivas: permite laços e condicionais no próprio template, com uma sintaxe própria (ex.: FreeMarker, JSP, ERB)

O FreeMarker adota a segunda filosofia: por isso existem diretivas como <#list> e <#if>.

O FreeMarker

O que é o FreeMarker

  • Motor de templates de propósito geral para Java: gera HTML, mas também e-mails, XML e arquivos de configuração
  • Projeto de código aberto, hoje mantido pela Apache Software Foundation
  • Em desenvolvimento desde o final da década de 1990, um dos motores de template mais antigos ainda ativos no ecossistema Java

Alternativas no ecossistema Java

  • JSP: abordagem original do Java EE, mistura código Java diretamente no HTML
  • Thymeleaf: mais recente, com sintaxe embutida em atributos HTML válidos; hoje é a opção destacada pela documentação oficial do Spring Boot
  • Velocity: outro veterano da Apache, hoje com atividade de desenvolvimento bem menor

Nenhuma opção é definitivamente melhor: são escolhas diferentes de sintaxe e filosofia.

Por que FreeMarker nesta disciplina

  • A sintaxe usa diretivas explícitas (${}, <#list>, <#if>), fáceis de distinguir do HTML ao redor
  • No Thymeleaf, a lógica fica dentro de atributos HTML comuns (th:each, th:if), o que pode confundir quem vê o conceito pela primeira vez
  • A separação visual entre "isto é HTML" e "isto é lógica de template" favorece o aprendizado inicial

Construindo o cardápio, passo a passo

A dependência no pom.xml

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-freemarker</artifactId></dependency>
  • Templates em src/main/resources/templates/
  • Extensão .ftlh: escape automático de HTML
  • Associe .ftlh a HTML no editor para ter destaque de sintaxe

Um cardápio estático

<!-- cardapio.ftlh --><h1>Cardápio</h1><p>Confira as opções do dia no balcão.</p>

Por enquanto, um arquivo HTML comum: nada de dinâmico ainda.

Servindo o cardápio

@Controllerpublic class CardapioController {    @GetMapping("/cardapio")    public String cardapio() {        return "cardapio";    }}

O retorno é o nome do template, não o corpo da resposta.

@Controller x @RestController

  • @RestController: o retorno é o corpo da resposta
  • @Controller: o retorno é um nome de view, resolvido para um .ftlh

Métodos que devem devolver texto cru precisam de @ResponseBody.

Adicionando uma variável

<!-- cardapio.ftlh --><h1>Cardápio</h1><p>Sugestão do dia: ${itemDoDia}</p>

${nome} imprime uma variável; falta o controller enviar esse valor.

Enviando a variável com Model

@GetMapping("/cardapio")public String cardapio(Model model) {    model.addAttribute("itemDoDia", "Cappuccino");    return "cardapio";}

O nome usado em addAttribute precisa bater com o nome usado no template.

Comentários do FreeMarker

<#-- Esta linha some do HTML final --><h1>Cardápio</h1><p>Sugestão do dia: ${itemDoDia}</p>

Diferente do comentário HTML (<!-- -->), que é enviado ao navegador.

A diretiva <#list>

<h1>Cardápio</h1><ul><#list bebidas as bebida>    <li>${bebida.nome}: R$ ${bebida.preco}</li></#list></ul>

Repete o bloco interno para cada elemento da coleção; falta o controller enviar bebidas.

Passando a lista pelo Model

model.addAttribute("bebidas", repositorio.listarTodas());

Uma List Java vira, no template, uma coleção percorrível com <#list>.

Formatando números com ?c

${totalVendas}<!-- 12,345 ou 12.345, conforme o idioma do navegador -->${totalVendas?c}<!-- 12345, sempre no mesmo formato -->

Por padrão, o FreeMarker formata números pela localização do navegador; ?c evita isso, inclusive em ${bebida.preco?c}.

A diretiva <#if>

<#if bebidas?size == 0>    <p>Nenhuma bebida cadastrada.</p><#else>    <ul>    <#list bebidas as bebida>        <li>${bebida.nome}: R$ ${bebida.preco?c}</li>    </#list>    </ul></#if>

?size é um built-in: consulta uma propriedade do valor à esquerda.

Reaproveitando templates

A diretiva <#include>

<!-- cabecalho.ftlh --><header><h1>Cafeteria Central</h1></header>
<!-- cardapio.ftlh --><#include "cabecalho.ftlh"><p>Sugestão do dia: ${itemDoDia}</p>

Insere o conteúdo de outro template no ponto indicado.

Obrigado!

Prof. Me. Danilo Bueno
[email protected]