102 freemarker page static technology

freemarker page static technology

    • 1.1 freemarker introduction
    • 1.2 Environment setup & amp; & amp;Quick start
      • 1.2.1 Create test project
      • 1.2.2 Configuration file
      • 1.2.3 Create model class
      • 1.2.4 Create template
      • 1.2.5 Create controller
      • 1.2.6 Create startup class
      • 1.2.7 Testing
    • 1.3 freemarker basics
      • 1.3.1 Basic grammar types
      • 1.3.2 Collection instructions (List and Map)
      • 1.3.3 if instruction
      • 1.3.4 Operators
      • 1.3.5 Null value handling
      • 1.3.6 Built-in functions
    • 1.4 Static testing
      • 1.4.1 Requirements analysis
      • 1.4.2 Static testing

1.1 freemarker introduction

FreeMarker is a template engine: a universal tool for generating output text (HTML web pages, emails, configuration files, source code, etc.) based on templates and data to be changed. It is not for end users, but a Java class library, a component that programmers can embed into the products they develop.

Templates are written in FreeMarker Template Language (FTL). It is a simple, specialized language, not a full-blown programming language like PHP. That means preparing the data for display in real programming languages, such as database queries and business operations, and then the template displays the prepared data. In the template, you can focus on how to display the data, and outside the template, you can focus on what data to display.

Template + data = static file

What other commonly used java template engines are there?

Jsp, Freemarker, Thymeleaf, Velocity, etc.

  1. Jsp is dedicated to Servlet and cannot be used alone.

  2. Thymeleaf is a new technology with more powerful functions, but its execution efficiency is relatively low.

  3. Velocity has not been updated since version 2.0 in 2010. Spring Boot officially no longer supports this after version 1.4. Although Velocity was iterated in the 2017 version, it was too late.

1.2 Environment Setup & amp; & amp;Quick Start

Freemarker is a view format of springmvc. SpringMVC supports freemarker view format by default.

A Spring Boot + Freemarker project needs to be created for testing the template.

1.2.1 Create test project

Create a freemarker-demo test project specifically for freemarker functional testing and template testing.

pom.xml is as follows

<properties>
  <maven.compiler.source>8</maven.compiler.source>
  <maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
  <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>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
  </dependency>
  <!-- lombok -->
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
  </dependency>

  <!-- apache's encapsulation tool library for java io -->
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
  </dependency>
</dependencies>

1.2.2 Configuration File

Configure application.yml

server:
  port: 8881 #Service port
spring:
  application:
    name: freemarker-test #Specify service name
  freemarker:
    cache: false #Turn off template caching to facilitate testing
    settings:
      template_update_delay: 0 #Check the template update delay time. Set to 0 to check immediately. If the time is greater than 0, caching will be inconvenient for template testing.
    suffix: .ftl #Specify the suffix name of the Freemarker template file

1.2.3 Create model class

Create a model type under the freemarker test project for testing

package com.it.pojo;

import lombok.Data;

import java.util.Date;

@Data
public class Student {<!-- -->
    private String name;//name
    private int age;//Age
    private Date birthday;//birthday
    private Float money;//wallet
}

1.2.4 Create template

Create templates under resources. This directory is the default template storage directory of freemarker.

Create the template file 01-basic.ftl under templates. The interpolation expression in the template will eventually be replaced by freemarker with specific data.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
</head>
<body>
<b>Normal text String display:</b><br><br>
Hello ${name}<br>

<b>Data display in the object Student:</b><br/>
Name: ${stu.name}<br/>
Age: ${stu.age}

</body>
</html>

1.2.5 Create controller

Create the Controller class, add name to the Map, and finally return the template file.

package com.it.freemarker.controller;

import com.it.freemarker.pojo.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.Date;

/**
 * @Description:
 * @Version: V1.0
 */
@Controller // ***
public class HelloController {<!-- -->


    @GetMapping("/basic")
    public String basic(Model model) {<!-- -->

        // String data
        model.addAttribute("name", "freemarker");

        //object data
        Student student = new Student();
        student.setAge(18);
        student.setBirthday(new Date());
        student.setMoney(9000F);
        student.setName("Xiao Ming");
        model.addAttribute("stu", student);

        // find page
        return "01-basic";

    }
}

01-basic.ftl, fill data using interpolation expressions

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
</head>
<body>
<b>Normal text String display:</b><br><br>
Hello ${name}<br>

<b>Data display in the object Student:</b><br/>
Name: ${stu.name}<br/>
Age: ${stu.age}

</body>
</html>

1.2.6 Create startup class

package com.it.freemarker;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FreemarkerApplication {<!-- -->
    public static void main(String[] args) {<!-- -->
        SpringApplication.run(FreemarkerDemotApplication.class,args);
    }
}

1.2.7 Test

Request: http://localhost:8881/basic

1.3 freemarker basics

1.3.1 Basic grammar types

1. Comments, i.e. <#-- -->, the content between them will be ignored by freemarker

<#--I am a freemarker comment-->

2. Interpolation: In the ${..} part, freemarker will replace **${..} with the real value **

Hello

3. FTL command: Similar to HTML tags, add # before the name to distinguish it. Freemarker will parse the expression or logic in the tag.

<# >FTL command</#>

4. Text, only text information. Contents that are not comments, interpolations, and FTL instructions of freemarker will be ignored and parsed by freemarker and the content will be output directly.

<#--Normal text in freemarker-->
I am an ordinary text

1.3.2 Collection instructions (List and Map)

1. Data model:

Add the following methods in HelloController:

@GetMapping("/list")
public String list(Model model){<!-- -->

    //----------------------------------------
    Student stu1 = new Student();
    stu1.setName("Xiao Ming");
    stu1.setAge(18);
    stu1.setMoney(1000.86f);
    stu1.setBirthday(new Date());

    //Xiaohong object model data
    Student stu2 = new Student();
    stu2.setName("小红");
    stu2.setMoney(200.1f);
    stu2.setAge(19);

    //Store the two object model data into the List collection
    List<Student> stus = new ArrayList<>();
    stus.add(stu1);
    stus.add(stu2);

    //Store the List collection data in the model
    model.addAttribute("stus",stus);

    //----------------------------------------

    //Create Map data
    HashMap<String,Student> stuMap = new HashMap<>();
    stuMap.put("stu1",stu1);
    stuMap.put("stu2",stu2);
    // 3.1 Store Map data in the model
    model.addAttribute("stuMap", stuMap);

    return "02-list";
}

2. Template:

Add 02-list.ftl file in templates

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
</head>
<body>
    
<#-- Display of list data -->
<b>Display the stu data in the list:</b>
<br>
<br>
<table>
    <tr>
        <td>Serial number</td>
        <td>Name</td>
        <td>Age</td>
        <td>Wallet</td>
    </tr>
    <#list stus as stu>
        <tr>
            <td>${stu_index + 1}</td>
            <td>${stu.name}</td>
            <td>${stu.age}</td>
            <td>${stu.money}</td>
        </tr>
    </#list>

</table>

    
<#-- Display of Map data -->
<b>Display of map data:</b>
<br/><br/>
<a href="###">Method 1: Through map['keyname'].property</a><br/>
Output student information of stu1:<br/>
Name: ${stuMap['stu1'].name}<br/>
Age: ${stuMap['stu1'].age}<br/>
<br/>
<a href="###">Method 2: Through map.keyname.property</a><br/>
Output student information of stu2:<br/>
Name: ${stuMap.stu2.name}<br/>
Age: ${stuMap.stu2.age}<br/>

<br/>
<a href="###">Traverse the two student information in the map:</a><br/>
<table>
    <tr>
        <td>Serial number</td>
        <td>Name</td>
        <td>Age</td>
        <td>Wallet</td>
    </tr>
    <#list stuMap?keys as key >
        <tr>
            <td>${key_index}</td>
            <td>${stuMap[key].name}</td>
            <td>${stuMap[key].age}</td>
            <td>${stuMap[key].money}</td>
        </tr>
    </#list>
</table>

 
</body>
</html>

Explanation of the above code:

${k_index}:
Index: Get the subscript of the loop. To use it, add “_index” after stu. Its value starts from 0.

1.3.3 if directive

? The if instruction is a judgment instruction, which is a commonly used FTL instruction. Freemarker will make a judgment when it encounters if during parsing. If the condition is true, the content in the if will be output, otherwise the content will be skipped and will not be output.

  • Command format
<#if expression>
true content display
</#if>
    
<#if expression>
true content display
    <#else>
    false content display
</#if>

1. Data model:

Use the list command to test the data model and determine that the data font named Xiaohong is displayed in red.

2. Template:

<table>
    <tr>
        <td>Name</td>
        <td>Age</td>
        <td>Wallet</td>
    </tr>
    <#list stus as stu>
        <tr>
            <td >${stu.name}</td>
            <td>${stu.age}</td>
            <td >${stu.mondy}</td>
        </tr>
    </#list>

</table>

Example code:

<table>
    <tr>
        <td>Name</td>
        <td>Age</td>
        <td>Wallet</td>
    </tr>
    <#list stus as stu>
        <#if stu.name='小红'>
            <tr style="color: red">
                <td>${stu_index}</td>
                <td>${stu.name}</td>
                <td>${stu.age}</td>
                <td>${stu.money}</td>
            </tr>
            <#else>
            <tr>
                <td>${stu_index}</td>
                <td>${stu.name}</td>
                <td>${stu.age}</td>
                <td>${stu.money}</td>
            </tr>
        </#if>
    </#list>
</table>

3. Output:

If the name is “Xiao Ming”, the font color will be displayed in red.

1.3.4 Operators

1. Arithmetic operators

Arithmetic operations are fully supported in FreeMarker expressions. The arithmetic operators supported by FreeMarker include:

  • Addition: +
  • Subtraction: -
  • Multiplication: *
  • Division: /
  • Find the modulus (remainder): %

template code

<b>Arithmetic operators</b>
<br/><br/>
    100 + 5 operation: ${100 + 5}<br/>
    100 - 5 * 5 operation: ${100 - 5 * 5}<br/>
    5 / 2 operation: ${5 / 2}<br/>
    12 % 10 operation: ${12 % 10}<br/>

Except for the + operation, other operations can only be calculated with the number type.

2. Comparison operators

  • =or==: Determine whether two values are equal.
  • !=: Determine whether two values are not equal.
  • >orgt: Determine whether the value on the left is greater than the value on the right
  • >=orgte: Determine whether the value on the left is greater than or equal to the value on the right
  • <orlt: Determine whether the value on the left is less than the value on the right
  • <=orlte: Determine whether the value on the left is less than or equal to the value on the right

Controller’s data model code

@GetMapping("operation")
public String testOperation(Model model) {<!-- -->
    //Construct Date data
    Date now = new Date();
    model.addAttribute("date1", now);
    model.addAttribute("date2", now);
    
    return "03-operation";
}

= and == template code

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
</head>
<body>

    <b>Comparison operators</b>
    <br/>
    <br/>

    <dl>
        <dt> == and != comparison: </dt>
        <dd>
            <#if "xiaoming" == "xiaoming">
                String comparison "xiaoming" == "xiaoming"
            </#if>
        </dd>
        <dd>
            <#if 10 != 100>
                Comparison of values 10 != 100
            </#if>
        </dd>
    </dl>

    <dl>
        <dt>Other comparisons</dt>
        <dd>
            <#if 10 gt 5 >
                Form 1: Use special characters to compare values 10 gt 5
            </#if>
        </dd>
        <dd>
            <#-- Date comparison requires converting the attribute to data type through ?date before comparison -->
            <#if (date1?date >= date2?date)>
                Form 2: Use parentheses to compare times date1?date >= date2?date
            </#if>
        </dd>
    </dl>

    <br/>

</body>
</html>

Note on comparison operators

  • **= and !=** can be used to compare strings, values and dates for equality.
  • **=and!=**Both sides must be the same type of value, otherwise an error will occur
  • String"x", "x ", **"X" **The comparison is not unequal. Because FreeMarker is an exact comparison
  • Other operators can operate on numbers and dates, but not on strings
  • Using alphabetic operators such as **gt instead of > will have better results, because FreeMarker will >** is interpreted as the end character of the FTL tag
  • You can use parentheses to avoid this situation, such as:<#if (x>y)>

3. Logical operators

  • Logical AND: & amp; & amp;
  • Logical OR: ||
  • Logical negation:!

Logical operators can only operate on Boolean values, otherwise an error will occur.

template code

<b>Logical operators</b>
    <br/>
    <br/>
    <#if (10 lt 12 ) & amp; & amp;( 10 gt 5 ) >
        (10 lt 12 ) & amp; & amp;( 10 gt 5 ) is shown as true
    </#if>
    <br/>
    <br/>
    <#if !false>
        False is inverted to true
    </#if>

1.3.5 Null value handling

1. Use “” to determine whether a variable exists

Usage: variable, if the variable exists, return true, otherwise return false

Example: To prevent an error when stus is empty, you can add the following judgment:

 <#if stus>
    <#list stus as stu>
    ...
    </#list>
    </#if>

2. Use “!” as the default value for missing variables

  • Use ! to specify a default value and display the default value when the variable is empty.

    Example: ${name!’} means if name is empty, an empty string will be displayed.

  • If it is a nested object, it is recommended to use () to enclose it

    Example: ${(stu.bestFriend.name)!’} means that if stu or bestFriend or name is empty, an empty string will be displayed by default.

1.3.6 Built-in functions

Built-in function syntax format: Variable + ? + function name

1. Sum to the size of a certain set

${collection name?size}

2. Date formatting

Display year, month and day: ${today?date}
Display hours, minutes and seconds: ${today?time}
Display date + time: ${today?datetime}
Custom formatting: ${today?string("MM month of yyyy year")}

3. Built-in functions c

model.addAttribute(“point”, 102920122);

Point is a numeric type. Using ${point} will display the value of this number. Every three digits are separated by commas.

If you don’t want to display numbers separated by three digits, you can use the c function to convert the number into a string for output.

${point?c}

4. Convert json string into object

one example:

The assign tag is used, and the role of assign is to define a variable.

<#assign text="{'bank':'ICBC','account':'10101920201920212'}" />
<#assign data=text?eval />
Account opening bank: ${data.bank} Account number: ${data.account}

Built-in function template page:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>inner Function</title>
</head>
<body>

    <b>Get collection size</b><br>

    Collection size: ${stus?size}
    
    <b>Obtained date</b><br>

    Display year, month and day: ${today?date}<br>

    Display hours, minutes and seconds: ${today?time}<br>

    Display date + time: ${today?datetime}<br>

    Custom formatting: ${today?string("YyyyYearMMMonth")}<br>
    
    <b>Built-in function C</b><br>
    There is no numerical value displayed by the C function: ${point}<br>
    There is a value displayed by the C function: ${point?c}
    
    <b>Declare variable assign</b><br>
    <#assign text="{'bank':'ICBC','account':'10101920201920212'}" />
    <#assign data=text?eval />
    Account opening bank: ${data.bank} Account number: ${data.account}


</body>
</html>

Built-in function Controller data model:

@GetMapping("innerFunc")
public String testInnerFunc(Model model) {<!-- -->
    //1.1 Xiaoqiang object model data
    Student stu1 = new Student();
    stu1.setName("Xiaoqiang");
    stu1.setAge(18);
    stu1.setMoney(1000.86f);
    stu1.setBirthday(new Date());
    //1.2 Xiaohong object model data
    Student stu2 = new Student();
    stu2.setName("小红");
    stu2.setMoney(200.1f);
    stu2.setAge(19);
    //1.3 Store the two object model data into the List collection
    List<Student> stus = new ArrayList<>();
    stus.add(stu1);
    stus.add(stu2);
    model.addAttribute("stus", stus);
    // 2.1 Add date
    Date date = new Date();
    model.addAttribute("today", date);
    // 3.1 Add value
    model.addAttribute("point", 102920122);
    return "04-innerFunc";
}

For more grammar learning, please refer to the official website: http://freemarker.foofun.cn/toc.html

1.4 Static testing

Previous tests used SpringMVC to integrate Freemarker into the project as a view parser (ViewReporter). During work, sometimes it is necessary to use Freemarker's native API to generate static content. Let's learn how to generate text files using the native API.

1.4.1 Requirements Analysis

Use freemarker's native API to generate html files from the page. This section tests the method of generating html files:

1.4.2 Static testing

Generate html files based on template files

①: Modify the application.yml file and add the following configuration information for the template storage location. The complete configuration is as follows:

server:
  port: 8881 #Service port
spring:
  application:
    name: freemarker-demo #Specify service name
  freemarker:
    cache: false #Turn off template caching to facilitate testing
    settings:
      template_update_delay: 0 #Check the template update delay time. Set to 0 to check immediately. If the time is greater than 0, caching will be inconvenient for template testing.
    suffix: .ftl #Specify the suffix name of the Freemarker template file
    template-loader-path: classpath:/templates/ #template storage location

②: Create a test class under test

package com.it.freemarker.test;

import com.it.freemarker.FreemarkerDemoApplication;
import com.it.freemarker.entity.Student;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

@SpringBootTest(classes = FreemarkerDemoApplication.class)
@RunWith(SpringRunner.class)
public class FreemarkerTest {<!-- -->

    @Autowired
    private Configuration configuration;

    @Test
    public void test() throws IOException, TemplateException {<!-- -->
        //freemarker template object, get the template
        Template template = configuration.getTemplate("02-list.ftl");
        Map params = getData();
        //synthesis
        //First parameter data model
        //Second parameter output stream
        template.process(params, new FileWriter("d:/list.html"));
    }

    private Map getData() {<!-- -->
        Map<String, Object> map = new HashMap<>();

        //Object model data
        Student stu1 = new Student();
        stu1.setName("Xiao Ming");
        stu1.setAge(18);
        stu1.setMoney(1000.86f);
        stu1.setBirthday(new Date());

        //Xiaohong object model data
        Student stu2 = new Student();
        stu2.setName("小红");
        stu2.setMoney(200.1f);
        stu2.setAge(19);

        //Store the two object model data into the List collection
        List<Student> stus = new ArrayList<>();
        stus.add(stu1);
        stus.add(stu2);

        //Store List collection data in map
        map.put("stus", stus);


        //Create Map data
        HashMap<String, Student> stuMap = new HashMap<>();
        stuMap.put("stu1", stu1);
        stuMap.put("stu2", stu2);
        //Store Map data in map
        map.put("stuMap", stuMap);

        //Return to Map
        return map;
    }
}