同福

Java的模板引擎FreeMarker的自动配置使用技巧【20210608】

介绍

介绍

开发一个网站需要考虑几个问题,首先就是编程语言,其次就是开发框架,最后还需要考虑模板引擎。编程语言这里我们自然是Java语言了;开发框架就是编写网站后端功能模块的基础框架,这里福哥选择的是TFSpring框架;最后的模板引擎,就是在制作用户界面所使用的处理模块,也就是MVC架构里面说的视图,这里福哥就要引出今天的主角FreeMarker了。

FreeMarker是非常有名的基于Java语言的模板引擎,它支持非常丰富的语法,它有非常好的开发团队,所以福哥才会在TFSpring框架里面将FreeMarker作为模板引擎来使用。

福哥以前的编程习惯是在代码里面手动加载库,手动调用配置对象进行配置,手动初始化对象。但是Spring Boot框架的精髓就是自动配置,就是让我们把配置的事情都交给框架来处理,我们只需要关注业务本身就可以。所以福哥打算陆续地把之前学习的基于Spring Boot框架使用各种工具、驱动、引擎库的教程再搞一遍自动配置版本给大家。

安装

依赖

这是freemarker的依赖,写到pom.xml里面就可以了。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

配置

我们需要在application.properties里面配置一下。

##############################################################################
# free marker
##############################################################################

spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.check-template-location=true
spring.freemarker.expose-request-attributes=true
spring.freemarker.allow-session-override=true
spring.freemarker.request-context-attribute=request
spring.freemarker.suffix=.ftl

示例

下面是一个标准的freemarker的示例。

控制器

首先我们建立一个控制器对象,给这个对象加上@Controller注解(注意是@Controller注解不是@RestController注解),然后freemarker就会在用户请求进入的时候接管请求映射控制权去调用对应的模板了。

@Controller
public class DemoPageController {

}

Java

建立了一个请求映射将请求路径“/net.tongfu.tfspring.freemarker”映射到模板“net.tongfu.net.tfspring.freemarker”上面,请求路径和模板路径不需要一一对应,但是为了方便管理还是对应起来比较好。

@RequestMapping("/net.tongfu.tfspring.freemarker")
public String responseFreeMarker(){

    return "net.tongfu.tfspring.freemarker";
}

模板

模板文件是test.ftl,这里福哥只写了一句话。

福哥,你好!

效果

home/topic/2021/0609/19/c10b73b3c13ec0184a4a858709d16b02.png

目录结构

这是福哥的目录结构。

home/topic/2021/0609/19/24bc59db89158519d45ab06dd14b36a8.png

使用

福哥写了一个示例,演示如何将后端程序的变量指定给前端模板来使用的。

实体User

这是实体User的定义。

@Data
public class User {
    Integer id;
    String name;
    String link;
}

Java

下面演示如何向前端模板指定变量。

@RequestMapping("/net.tongfu.tfspring.freemarker")
public String responseFreeMarker(ModelMap data){
    data.put("int", 10);
    data.put("double", 1.2);
    data.put("string", "福哥");
    data.put("html", "<h3>福哥</h3>");

    User user = new User();
    user.setId(35);
    user.setName("鬼谷子叔叔");
    user.setLink("https://tongfu.net/home/35.html");
    data.put("entity", user);

    return "net.tongfu.tfspring.freemarker";
}

模板

下面是前端模板代码的示例。

<table border="1">
    <tr>
        <td>整型</td><td>${int}</td>
    </tr>
    <tr>
        <td>双精</td><td>${double}</td>
    </tr>
    <tr>
        <td>字符串</td><td>${string}</td>
    </tr>
    <tr>
        <td>HTML</td><td>${html}</td>
    </tr>
    <tr>
        <td>实体</td><td>
            <a href="${entity.link}">(${entity.id})${entity.name}</a>
        </td>
    </tr>
</table>

效果

执行程序可以看到如下的页面效果。

home/topic/2021/0609/19/95c7de684e2b0d69365f780285b9fca7.png

语法

变量

  • 模板变量使用${...}表示,“...”就是Map对象的键名。

  • 模板变量如果是一个结构可以通过${xxx.yyy}调用结构属性,“xxx”是结构对应的Map对象的键名,“yyy”是结构的属性名称。

实体User

@Data
public class User {
    Integer id;
    String name;
    String link;
}

Java

@RequestMapping("/net.tongfu.tfspring.freemarker")
public String responseFreeMarker(ModelMap data){
    data.put("name", "同福");
    
    User user = new User();
    user.setId(35);
    user.setName("鬼谷子叔叔");
    user.setLink("https://tongfu.net/home/35.html");
    data.put("entity", user);

    return "net.tongfu.tfspring.freemarker";
}

前端模板

<table border="1">
    <tr>
        <td>普通变量</td><td>${name}</td>
    </tr>
    <tr>
        <td>结构变量</td><td>
            <a href="${entity.link}">(${entity.id})${entity.name}</a>
        </td>
    </tr>
</table>

效果

home/topic/2021/0609/19/220fa1ebae3ae4f7fc1e30eeed00f6e7.png

遍历循环

  • 对集合变量进行遍历,就可以拿到集合的一个一个的元素。

  • 对Map变量进行遍历,就可以拿到Map的键名和键。

Java

@RequestMapping("/net.tongfu.tfspring.freemarker")
public String responseFreeMarker(ModelMap data){
    Map user = new LinkedHashMap();
    user.put("id", 35);
    user.put("name", "鬼谷子叔叔");
    user.put("link", "https://tongfu.net/home/35.html");

    data.put("user", user);

    return "net.tongfu.tfspring.freemarker";
}

模板

<table border="1">
    <tr>
        <td>索引</td><td>Key</td><td>Item</td>
    </tr>
    <#list user ? keys as key>
    <tr>
        <td>${key_index}</td><td>${key}</td><td>${user[key]}</td>
    </tr>
    </#list>
</table>

效果

home/topic/2021/0609/19/d7f3b2ed4ee50b2ddddf44103fd985ca.png

按次循环

  • 按次循环需要知道起始数值和结束数值,对应数组循环的话需要考虑结束值是数组长度减一。

Java

@RequestMapping("/net.tongfu.tfspring.freemarker")
public String responseFreeMarker(ModelMap data){
    String[] languages = new String[]{
            "PHP",
            "Python",
            "Java",
            "JavaScript",
            "C/C++",
            "Asp.net"
    };
    
    data.put("lang", languages);

    return "net.tongfu.tfspring.freemarker";
}

模板

<table border="1">
    <tr>
        <td>索引</td><td>语言</td>
    </tr>
    <#list 0..5 as i>
    <tr>
        <td>${i}</td><td>${lang[i]}</td>
    </tr>
    </#list>
</table>

效果

home/topic/2021/0609/19/23ae73a2275d69ba60b72d6f1828809d.png

嵌套循环

  • 嵌套遍历循环需要注意子级名称的类型不要弄错了,后端Java要和前端模板严格对应。

Java

@RequestMapping("/net.tongfu.tfspring.freemarker")
public String responseFreeMarker(ModelMap data){
    List<Map<String, Object>> map = new LinkedList<>();
    Map<String, Object> item;
    item = new HashMap<>();
    item.put("hot", 100);
    item.put("lang", "PHP");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 200);
    item.put("lang", "Python");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 300);
    item.put("lang", "Java");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 60);
    item.put("lang", "JavaScript");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 30);
    item.put("lang", "C/C++");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 80);
    item.put("lang", "Asp.net");
    map.add(item);

    data.put("lang", map);

    return "net.tongfu.tfspring.freemarker";
}

模板

<table border="1">
    <tr>
        <td>热度</td><td>语言</td>
    </tr>
    <#list lang as langItem>
    <tr>
        <#list langItem ? keys as key>
        <td>${langItem[key]}</td>
        </#list>
    </tr>
    </#list>
</table>

效果

home/topic/2021/0609/19/de44da393c3400c555f4fe4778c6f6df.png

判断语句

  • 判断语句同样使用“&&”和“||”表示“与”和“或”关系,使用“==”和“!=”表示相等和不相等。

  • 判断语句“else if”需要连着写成“elseif”这样,否则会报错。

比较运算符

  • ==:表示两边相等

  • !=:表示两边不相等

  • gt:表示左边大于右边

  • gte:表示左边大于等于右边

  • lt:表示左边小于右边

  • lte:表示左边小于等于右边

Java

@RequestMapping("/net.tongfu.tfspring.freemarker")
public String responseFreeMarker(ModelMap data){
    List<Map<String, Object>> map = new LinkedList<>();
    Map<String, Object> item;
    item = new HashMap<>();
    item.put("hot", 100);
    item.put("lang", "PHP");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 200);
    item.put("lang", "Python");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 300);
    item.put("lang", "Java");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 60);
    item.put("lang", "JavaScript");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 30);
    item.put("lang", "C/C++");
    map.add(item);
    item = new HashMap<>();
    item.put("hot", 80);
    item.put("lang", "Asp.net");
    map.add(item);

    data.put("lang", map);

    return "net.tongfu.tfspring.freemarker";
}

模板

<table border="1">
    <tr>
        <td>热度</td><td>语言</td>
    </tr>
    <#list lang as langItem>
    <tr>
        <td>
            <#if langItem.hot gte 200>
            <span style="color: red;">${langItem.hot}</span>
            <#elseif langItem.hot gte 100>
            <span style="color: blue;">${langItem.hot}</span>
            <#else>
            <span>${langItem.hot}</span>
            </#if>
        </td>
        <td>
            ${langItem.lang}
        </td>
    </tr>
    </#list>
</table>

效果

home/topic/2021/0609/19/fa3b753f67186f8e639e6a053a76c6ca.png

总结

好了,今天福哥给童鞋们讲解了Java的模板引擎FreeMarker的使用技巧,相信大家今后无论是使用TFSpring框架开发项目,还是在自己的项目里面使用FreeMarker模板引擎,都可以制作出非常漂亮的用户界面了。