Génération de Pages Statiques avec Freemarker

  • Qu'est-ce que la génération de pages statiques ?

La génération de pages statiques consiste à convertir des pages web dynamiques en pages statiques.

  • Pourquoi utiliser la génération de pages statiques

  1. La génération de pages statiques et les techniques de mise en cache visent toutes deux à réduire la pression sur la base de données.
  2. La génération de pages statiques facilite l'indexation par les moteurs de recherche.
  3. La génération de pages statiques améliore la stabilité du site web.
  4. La génération de pages statiques permet d'augmenter la vitesse de chargement.
  • Qu'est-ce que Freemarker ?

Freemarker est un moteur de templates écrit en Java qui génère du texte en se basant sur des templates.

Freemarker est indépendant du conteneur Web, c'est-à-dire qu'il ne connaît pas les Servlets ou HTTP lors de son exécution.

Il peut être utilisé non seulement comme technologie de couche de présentation, mais aussi pour générer du XML, JSP ou du code Java.

Exemple d'implémentation

Test.html

<html>
<head>
    <meta charset="utf-8">
    <title>Introduction à Freemarker - Exemple simple</title>
</head>
<body>

Bienvenue sur notre blog technique : http://www.example-tech.com !

<h3>Directive assign</h3>
Contact : M. Dupont

Téléphone : 011223344  Adresse : 15 Rue de la Paix, Paris

<h3>Directive if</h3>
  Votre compte est vérifié

<h3>Directive list</h3>
---- Liste des produits ----<br>
  1 Produit : Pommes Prix : 3.5€<br>
  2 Produit : Bananes Prix : 1.8€<br>
  3 Produit : Oranges Prix : 2.2€<br>

<h3>Fonctions intégrées</h3>
<h4>Obtenir la taille d'une collection</h4>
Total :  3  enregistrements

<h4>Convertir une chaîne JSON en objet</h4>
    Banque : BNP Paribas  Numéro de compte : 987654321
    
<h4>Formatage de date</h4>
Date actuelle : 2023-5-15 <br>
Heure actuelle : 16:45:30 <br>   
Date et heure actuelles : 2023-5-15 16:45:30 <br>        
Format de date :  15 mai 2023

<h4>Conversion de nombre en chaîne</h4>
Points cumulés : 1,029,201,122
Points cumulés : 1029201122


<h3>Opérateur de traitement des valeurs nulles</h3>
<h4>Vérifier l'existence d'une variable : "??"</h4>
  La variable test n'existe pas

<h4>Valeur par défaut pour les variables manquantes : "!"</h4>
  -


<h3>Opérateurs</h3>
<h4>Opérateurs arithmétiques</h4>
Les expressions Freemarker prennent en charge complètement les opérations arithmétiques. Les opérateurs arithmétiques supportés par Freemarker incluent : +, - , * , / , %

<h4>Opérateurs logiques</h4>
Les opérateurs logiques sont les suivants : 
Opérateur ET :&& 
Opérateur OU :|| 
Opérateur NON :! 
Les opérateurs logiques ne peuvent s'appliquer qu'aux valeurs booléennes, sinon une erreur sera générée 

<h4>Opérateurs de comparaison</h4>
Les opérateurs de comparaison supportés dans les expressions sont les suivants : 
1  = ou ==: vérifie si deux valeurs sont égales. 
2  !=: vérifie si deux valeurs sont différentes. 
3  > ou gt: vérifie si la valeur de gauche est supérieure à celle de droite 
4  >= ou gte: vérifie si la valeur de gauche est supérieure ou égale à celle de droite 
5  < ou lt: vérifie si la valeur de gauche est inférieure à celle de droite  
6  <= ou lte: vérifie si la valeur de gauche est inférieure ou égale à celle de droite 
Note :  = et != peuvent être utilisés pour les chaînes, les nombres et les dates pour comparer l'égalité, mais = et != doivent être appliqués à des valeurs de même type, sinon une erreur sera générée. De plus, Freemarker effectue des comparaisons exactes, "x", "x " et "X" sont différents. Les autres opérateurs peuvent s'appliquer aux nombres et aux dates, mais pas aux chaînes. Dans la plupart des cas, l'utilisation d'opérateurs en lettres comme gt donne de meilleurs résultats que >, car Freemarker interprète > comme le caractère de fin de balise FTL. Bien sûr, on peut aussi utiliser des parenthèses pour éviter ce problème.

</body>
</html>

Code backend Exemple01

package com.example.tech.freemarker;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class PremierExemple {
    public static void main(String[] args) throws IOException, TemplateException {
        // 1. Créer une configuration
        Configuration configuration = new Configuration(Configuration.getVersion());
        // 2. Définir le répertoire des templates
        configuration.setDirectoryForTemplateLoading(
                new File("chemin/vers/les/templates"));
        // 3. Définir l'encodage des caractères
        configuration.setDefaultEncoding("utf-8");
        // 4. Charger le template
        Template template = configuration.getTemplate("exemple.ftl");
        // 5. Créer le modèle de données
        Map<String, Object> donnees = new HashMap<>();
        donnees.put("nomUtilisateur", "Alex Martin");
        donnees.put("message", "Bienvenue sur notre plateforme technique !");
        donnees.put("estAuthentifie", true);
        
        List<Map<String, Object>> articles = new ArrayList<>();
        
        Map<String, Object> article1 = new HashMap<>();
        article1.put("nom", "Ordinateurs portables");
        article1.put("prix", 899.99);
        
        Map<String, Object> article2 = new HashMap<>();
        article2.put("nom", "Smartphones");
        article2.put("prix", 599.99);
        
        Map<String, Object> article3 = new HashMap<>();
        article3.put("nom", "Tablettes");
        article3.put("prix", 349.99);
        
        articles.add(article1);
        articles.add(article2);
        articles.add(article3);
        
        donnees.put("listeArticles", articles);
        donnees.put("aujourdhui", new Date());
        donnees.put("totalPoints", 102920122);
        
        // 6. Créer un objet Writer
        Writer writer = new FileWriter(new File("chemin/vers/la sortie/exemple.html"));
        // 7. Générer le contenu
        template.process(donnees, writer);
        // 8. Fermer le Writer
        writer.close();
    }
}

Application de la génération de pages statiques à un site web

Template de blog detailBlog.ftl

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Python Django Template Layer (AJAX) - Blog Technique</title>
<link rel="stylesheet" href="./css/bootstrap.min.css">
<link rel="stylesheet"
    href="./css/bootstrap-theme.min.css">
<link rel="stylesheet" href="./css/blog.css">
<script src="./js/jquery-1.11.2.min.js"></script>
<script src="./js/bootstrap.min.js"></script>
<style type="text/css">
body {
    padding-top: 10px;
    padding-bottom: 40px;
}
</style>
</head>
<body>
    <div class="container">
        <script type="text/javascript">
            function validerRecherche() {
                var terme = document.getElementById("recherche").value.trim();
                if (terme == null || terme == "") {
                    alert("Veuillez entrer un terme de recherche !");
                    return false;
                } else {
                    return true;
                }
            }
        </script>


        <div class="row">
            <div class="col-md-12" style="padding-top: 10px">
                <nav class="navbar navbar-default navbar-fixed-top">
                <div class="container-fluid">
                    <!-- Brande et bouton regroupés pour un meilleur affichage mobile -->
                    <div class="navbar-header">
                        <button type="button" class="navbar-toggle collapsed"
                            data-toggle="collapse"
                            data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                            <span class="sr-only">Menu</span> <span class="icon-bar"></span> <span
                                class="icon-bar"></span> <span class="icon-bar"></span>
                        </button>
                        <a class="navbar-brand" href="http://www.example-tech.com/accueil"><b
                            style="color: black"><strong>Accueil</strong></b></a>

                    </div>

                    <!-- Liens de navigation, formulaires et autres contenu -->
                    <div class="collapse navbar-collapse"
                        id="bs-example-navbar-collapse-1">
                        - [****Technologie****](http://www.example-tech.com/tech)
- [****Tutoriels****](http://www.example-tech.com/tutoriels)
- [****À propos****](http://www.example-tech.com/a-propos)
                        <form action="http://www.example-tech.com/recherche"
                            class="navbar-form navbar-right" role="search" method="post"
                            onsubmit="return validerRecherche()">
                            <div class="form-group">
                                <input type="text" id="recherche" name="recherche" value="" class="form-control"
                                    placeholder="Entrez un terme de recherche...">
                            </div>
                            <button type="submit" class="btn btn-default">Rechercher</button>
                        </form>
                    </div>
                    <!-- /.navbar-collapse -->
                </div>
                <!-- /.container-fluid --> </nav>
            </div>
        </div>


        <div class="row" style="margin-top: 50px;">
            <!--
            Zone d'affichage du contenu du blog,
            Liste des articles -> liste.jsp
            Détail d'un article -> detail.jsp
            Résultats de recherche -> resultats.jsp
        -->
            <div class="col-md-9">

                <script type="text/javascript"
                    src="./js/shCore.js"></script>
                <link rel="stylesheet"
                    href="./css/shCoreDefault.css">
                <script type="text/javascript">
                    /*Cette page affiche le contenu détaillé d'un article de blog*/
                    SyntaxHighlighter.all();

                    function afficherAutresCommentaires() {
                        $(".autresCommentaires").show();
                    }

                    function chargerImage() {
                        document.getElementById("imageRand").src = "/static/system/jsp/common/image.jsp?"
                                + Math.random();
                    }

                    function soumettreCommentaire() {
                        var contenu = $("#commentaire").val();
                        var codeImage = $("#codeImage").val();
                        if (contenu == null || contenu == "") {
                            alert("Veuillez entrer votre commentaire !");
                        } else if (codeImage == null || codeImage == "") {
                            alert("Veuillez entrer le code de vérification !");
                        } else {
                            $.post("/commentaire/enregistrer", {
                                "contenu" : contenu,
                                'codeImage' : codeImage,
                                'article.id' : '323'
                            }, function(resultat) {
                                if (resultat.succes) {
                                    window.location.reload();
                                    alert("Commentaire envoyé avec succès ! Il sera affiché après validation.");
                                } else {
                                    alert(resultat.erreur);
                                }
                            }, "json");
                        }
                    }
                </script>

                <div class="data_list">
                    <div class="data_list_title">
                        ![](./images/blog_show_icon.png)
                        Détail de l'article
                    </div>
                    <div>
                        <div class="article_titre">
                            <h3>
                                <strong>${article.titre }</strong>
                            </h3>
                        </div>
                        <div class="article_partage">
                            <!-- Ici ajouter les boutons de partage -->
                        </div>
                        <div class="article_info">Publié le : 『${article.datePublication?datetime }』&nbsp;&nbsp;Catégorie : ${article.categorie }&nbsp;&nbsp;Vues(${article.vues })
                        </div>
                        <div class="article_contenu">${article.contenu }</div>
                    </div>
                </div>

            </div>
            <!-- Mise en page latérale -->
            <div class="col-md-3">
                <div class="data_list">
                    <div class="data_list_title">À propos de l'auteur</div>
                    <div class="user_image">

                        ![](./images/profil_auteur.jpg)
                    </div>
                    <div class="nickName">Alex Martin - Développeur</div>
                    <div class="userSign">(La technologie transforme le monde)</div>
                </div>

                <div class="data_list">
                    <div class="data_list_title">
                        ![](./images/categories_icon.png) Par catégorie
                    </div>
                    <div class="datas">
                        - <span>[Java(45)](http://www.example-tech.com/categorie/java)</span>
- <span>[Web(32)](http://www.example-tech.com/categorie/web)</span>
- <span>[Mobile(28)](http://www.example-tech.com/categorie/mobile)</span>
- <span>[Cloud(19)](http://www.example-tech.com/categorie/cloud)</span>
- <span>[Sécurité(15)](http://www.example-tech.com/categorie/securite)</span>
- <span>[Bases de données(12)](http://www.example-tech.com/categorie/base-de-donnees)</span>
- <span>[Intelligence Artificielle(9)](http://www.example-tech.com/categorie/ia)</span>
- <span>[DevOps(7)](http://www.example-tech.com/categorie/devops)</span>
                    </div>
                </div>

                <div class="data_list">
                    <div class="data_list_title">
                        ![](./images/date_icon.png) Par date
                    </div>
                    <div class="datas">
                        - <span>[2023年05月(12)](http://www.example-tech.com/archives/2023/05)</span>
- <span>[2023年04月(18)](http://www.example-tech.com/archives/2023/04)</span>
- <span>[2023年03月(24)](http://www.example-tech.com/archives/2023/03)</span>
- <span>[2023年02月(15)](http://www.example-tech.com/archives/2023/02)</span>
- <span>[2023年01月(9)](http://www.example-tech.com/archives/2023/01)</span>
                    </div>
                </div>

                <div class="data_list">
                    <div class="data_list_title">
                        ![](./images/liens_icon.png) Liens utiles
                    </div>
                    <div class="datas">
                        - <span>[GitHub](https://www.github.com/)</span>
- <span>[Stack Overflow](https://stackoverflow.com/)</span>
- <span>[MDN Web Docs](https://developer.mozilla.org/)</span>
                    </div>
                </div>

            </div>
        </div>

        <div class="row">
            <div class="col-md-12">
                <div align="center" style="padding: 20px">
                    <span style="float: left;">Propulsé par <a
                        href="http://www.example-tech.com/" target="_blank">Blog Technique</a> V2.0
                    </span> Copyright © 2023 Example-Tech Tous droits réservés
                </div>
            </div>
        </div>
    </div>
</body>
</html>

Code backend Exemple02

package com.example.tech.freemarker;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import com.example.tech.util.ConnexionBDD;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class DeuxiemeExemple {
    @SuppressWarnings("rawtypes")
    public static void main(String[] args) throws IOException, TemplateException, SQLException {
        // 1. Créer une configuration
        Configuration configuration = new Configuration(Configuration.getVersion());
        // 2. Définir le répertoire des templates
        configuration.setDirectoryForTemplateLoading(
                new File("chemin/vers/les/templates"));
        // 3. Définir l'encodage des caractères
        configuration.setDefaultEncoding("utf-8");
        // 4. Charger le template
        Template template = configuration.getTemplate("detailBlog.ftl");
        genererPages(template);
        
    }
    
    private static void genererPages(Template template) throws SQLException, IOException, TemplateException {
        Connection connexion = ConnexionBDD.getConnexion();
        String sql = "SELECT * FROM articles_blog";
        PreparedStatement pst = connexion.prepareStatement(sql);
        ResultSet rs = pst.executeQuery();
        Map<String, Object> donnees = new HashMap<>();
        Map<String, Object> article = new HashMap<>();
        
        while(rs.next()) {
            article.put("id", rs.getObject("id"));
            article.put("titre", rs.getObject("titre"));
            article.put("datePublication", rs.getObject("date_publication"));
            article.put("categorie", rs.getObject("categorie"));
            article.put("vues", rs.getObject("vues"));
            article.put("contenu", rs.getObject("contenu"));
            
            donnees.put("article", article);
            
            // 6. Créer un objet Writer
            Writer writer = new FileWriter(new File("chemin/vers/la sortie/"+article.get("id")+".html"));
            // 7. Générer le contenu
            template.process(donnees, writer);
            // 8. Fermer le Writer
            writer.close();
        }
        ConnexionBDD.fermer(connexion, pst, rs);
    }
}

Étiquettes: Freemarker génération de pages statiques Java moteur de templates HTML

Publié le 30 juin à 02h04