Utilizando Apache FreeMarker com Spring Boot

Por Gaspar Barancelli Junior em 22 de janeiro de 2022

Apache Freemarker é um Template Engine desenvolvido em Java que tem por objetivo gerar saídas de texto (páginas da web HTML, e-mails, arquivos de configurações, código fonte, etc.) com base em modelos e dados variaveis. Os modelos são escritos em FreeMarker Templates (FTL), que é uma linguagem simples e especializada, onde você se concentra apenas em como apresentar os dados.

Em um projeto baseado em Spring Boot, devemos adicionar as seguintes dependências.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- Dependência responsável por fazer com que o FreeMarker suporte os novos objetos de datas disponíveis no Java 8 -->
<dependency>
    <groupId>no.api.freemarker</groupId>
    <artifactId>freemarker-java8</artifactId>
    <version>2.0.0</version>
</dependency>

O Apache FreeMarker requer algumas configurações básicas para funcionamento, então devemos definir as seguintes propriedades no arquivo de configuração application.properties.

# Diretório que contem os templates do FreeMarker
spring.freemarker.template-loader-path=classpath:/templates
# Sufixo dos templates
spring.freemarker.suffix=.ftl
# Indicamos a utilização dos macros do Spring nos templates do FreeMarker
spring.freemarker.expose-spring-macro-helpers=true

Também devemos configurar quais os diretórios que contem os recursos estáticos (CSS, JS, imagens, etc.) da nossa aplicação. Bem como configurar o Apache FreeMarker para suportar os novos Objetos de data.

Para isso devemos criar uma classe de configuração que implemente WebMvcConfigurer e também BeanPostProcessor.

import no.api.freemarker.java8.Java8ObjectWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

@Configuration
@EnableWebMvc
public class FreemarkerConfig implements BeanPostProcessor, WebMvcConfigurer {

    /**
        Após a criação de qualquer Bean feita pelo Spring esse método é invocado, por isso verificamos se o objeto Bean recebido por parâmetro é uma instancia de FreeMarkerConfigure, para que assim sejamos capazes de definir o Wrapper padrão do FreeMarker, definindo nossa dependência que sabe lidar com os novos objetos de Data do Java 8
    */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof FreeMarkerConfigurer) {
            FreeMarkerConfigurer configurer = (FreeMarkerConfigurer) bean;
            configurer.getConfiguration().setObjectWrapper(new Java8ObjectWrapper(freemarker.template.Configuration.getVersion()));
        }
        return bean;
    }

    /**
        Definimos que os arquivos estáticos a serem expostos se encontram no diretório resources e static que ficam no classpath da nossa aplicação, bem como também configuração a utilização de webjars.
    */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations(
                        "classpath:/META-INF/resources/",
                        "classpath:/resources/",
                        "classpath:/static/",
                        "/webjars/"
                );
    }

}

Com tudo configurado agora podemos criar um template FreeMarker, bem como um recurso estático e um endpoint responsável por retornar a página HTML gerada pelo FreeMarker.

Primeiramente vamos criar uma classe Java que será responsável por responder uma requisição HTTP feita pelo navegador. Ela tem apenas um endpoint que aceita requisição do verbo GET que sejam feitas no Path raiz da aplicação, e que retorna um objeto do tipo ModelAndView contendo o nome do nosso template do FreeMarker passando como variável para o template a data atual.

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.time.LocalDate;

@Controller
@RequestMapping("/")
public class IndexController {

    @GetMapping
    public ModelAndView get() {
        return new ModelAndView("index")
                .addObject("currentDate", LocalDate.now());
    }

}

O próximo passo é criarmos um arquivo estático (CSS) contendo um estilo para nossa aplicação.

h1 {
    color: green;
}

E por fim criamos nosso template FreeMarker que adiciona o arquivo CSS criado no passo anterior e que imprime a data atual formatada.

<html>
    <head>
        <title>FreeMarker and Spring Boot</title>
        <link rel="stylesheet" type="text/css" href="css/index.css" />
    </head>
    <body>
        <h1>
            ${currentDate.format("EEEE, dd 'de' MMMM 'de' yyyy")}
        </h1>
    </body>
</html>

Pelo navegador agora podemos fazer uma requisição para o endereço http://localhost:8080 e verificarmos que o HTML da resposta é o mesmo do código abaixo.

<html>
    <head>
        <title>FreeMarker and Spring Boot</title>
        <link rel="stylesheet" type="text/css" href="css/index.css" />
    </head>
    <body>
        <h1>
            sexta-feira, 06 de novembro de 2020
        </h1>
    </body>
</html>

O código fonte dessa aplicação esta no repositório hospedado no GitHub.

// Compartilhe esse Post

💫
🔥 NOVO APP

Domine o Inglês em 30 dias!

Inteligência Artificial + Repetição Espaçada • Método cientificamente comprovado

✅ Grátis para começar 🚀 Resultados rápidos
×