Freemarker简单概述及其数据类型的简单学习—快速入门(一)

FreeMarker的主要学习内容

一、FreeMarker概述

FreeMarker中文官方手册(可结合学习)http://freemarker.foofun.cn/

FreeMarker学习笔记源码git地址(可供下载):https://github.com/L-Melted/FreeMarkerDemo.git

1.FreeMarker概念

FreeMarker是一款模板引擎:即一种基于模板和要改变的数据,并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

模板编写为FreeMarker Template Language(FTL)。它是简单的,专用的语言,不是像PHP那样成熟的编程语言。那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算,之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据,而在模板之外可以专注于要展示什么数据。

这种方式通常被称为 MVC (模型 视图 控制器) 模式,对于动态网页来说,是一种特别流行的模式。 它帮助从开发人员(Java 程序员)中分离出网页设计师(HTML设计师)。设计师无需面对模板中的复杂逻辑, 在没有程序员来修改或重新编译代码时,也可以修改页面的样式。

FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序,将视图从业务逻辑中抽离处理,业务中不再包括视图的展示,而是将视图交给FreeMarker来输出。虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图):

FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件。

FreeMarker与容器无关,因为它并不知道HTTP或Servlet。FreeMarker同样可以应用于非Web应用程序环境。

FreeMarker更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库。 

2.FreeMarker特性

2.1通用目标:

能够生成各种文件:HTML、XML、RTF、Java源代码等等

易于嵌入到你的产品中:轻量级;不需要Servlet环境

插入式模板载入器:可以从任何源载入模板,如本地文件、数据库等等

你可以按你所需生成文本:保存到本地文件;作为Email发送;从web应用程序发送它返回给web浏览器

2.2强大的模板语言

所有常用的指令:include、if /else if/else 、循环结构

在模板中创建和改变变量

几乎在任何地方都可以使用复杂表达式来指定值

命名的宏,可以具有位置参数和嵌套内容

名字空间有助于建立和维护可重用的宏库,或将大工程分成模块,而不必担心名字冲突

输出转换块:在嵌套模板片段生成输出时,转化HTML转义、压缩、语法高亮等等;你可以定义自己的转换

2.3通用数据模型

FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示

你可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等等),告诉模板开发者使用方法,使其不受技术细节的打扰。

2.4为Web准备

在模板语言中内建处理典型web相关任务(如HTML转义)的结构

能够集成到Model2 Web应用框架中作为JSP的替代

支持JSP标记库

为MVC模式设计:分离可视化设计和应用程序逻辑;分离页面设计员和程序员

2.5智能的国际化和本地化

字符集智能化(内部使用UNICODE)

数字格式本地化敏感

日期和时间格式化敏感

非US字符集可以用作标识(如变量名)

2.6强大的xml处理能力

<#recurse>和<#visit>指令(2.3版本)用于递归遍历XML树。在模板中清楚和直接的访问XML对象模型。开源论坛JForum就是使用了FreeMarker作为页面模板。

3.FreeMarker环境搭建

3.1新建Maven Web项目

项目整体架构如下:

3.2配置坐标依赖和部署插件
pom文件配置:(主要是使用到的重要依赖,如果需要其他的,可以自行添加)

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xxxx</groupId>
    <artifactId>freemarker01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>freemarker01 Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <finalName>freemarker01</finalName>
        <plugins>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.2.1.v20140609</version>
            </plugin>
        </plugins>
    </build>
</project>

3.3修改配置文件web.xml:指定哪些文件是需要freemarker做处理的(放置在WEB-INF文件夹下面)

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <servlet>
        <servlet-name>freemarker</servlet-name>
        <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
        <init-param>
            <!--模板路径-->
            <param-name>TemplatePath</param-name>
            <!--默认在webapp目录下查找对应的模板文件-->
            <param-value>/</param-value>
        </init-param>

        <init-param>
            <!--模板默认的编码:UTF-8-->
            <param-name>default_encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </servlet>

    <!--处理所有以.ftl结尾的文件;ftl是freemarker默认的文件后缀-->
    <servlet-mapping>
        <servlet-name>freemarker</servlet-name>
        <url-pattern>*.ftl</url-pattern>
    </servlet-mapping>
</web-app>

3.4编写Servlet类

package com.xxx.servlet;

import com.xxx.entity.User;

import javax.jws.WebService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/f01")
public class FreeMarker01 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置数据(给模板设置数据)
        req.setAttribute("msg","hello freemarker!");
        //请求转发跳转到指定的模板页面 template/f01.ftl
        req.getRequestDispatcher("template/f01.ftl").forward(req,resp);
    }
}

3.5新建模板文件ftl (在webapp下面创建template文件夹,在其下面创建.ftl文件)

<!--
html注释:在浏览器中可以看到的注释
-->

<#--
    freemarker注释
        在浏览器中不能看到的注释
    freemarker的语法:
        1.html所有的标签都适用
        2.js与css的使用,与html中语法一致
-->

<#--获取数据 -->
${msg}

3.6启动项目

3.7访问项目

启动项目,在浏览器中输入Ip:port/url即可访问:http://localhost:9090/f01

二、FreeMarker 数据类型

FreeMarker模板中的数据类型由如下几种:

布尔型:等价于java的Boolean类型,不同的是不能直接输出,可转化为字符串输出

日期型:等价于java的Date类型,不同的是不能直接输出,需要转换为字符串再输出

数值型:等价于java中int,float,double等数值类型   (有三种显示形式:数值型(默认)、货币型、百分比型)

字符型:等价于java中的字符串,有很多内置函数

sequence类型:等价于java中的数组,list,set等集合类型

hash类型:等价于java中的Map类型

1、布尔类型

在Servlet中设置布尔类型的数据

package com.xxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 *  @author: liman
 *  @Date: 2020/12/18 15:46
 *  @Description: FreeMarker 数据类型
 */
@WebServlet("/f02")
public class FreeMarker02 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //布尔类型
        req.setAttribute("flag",true);

        //请求转发跳转到指定的模板页面 template/f02.ftl
        req.getRequestDispatcher("template/f02.ftl").forward(req,resp);

    }
}

在webapp的template文件下面创建f02.ftl文件获取数据

<h4>FreeMarker 数据类型</h4>
<#--
    FreeMarker 数据类型
        布尔类型
            在freeMarker页面中不能直接输出,如果要输出需要转换成字符串
            方式一:?c
            方式二:?string 或 ?string('为true时显示的内容','为false时显示的内容')
            方式三:?then('为true时显示的内容','为false时显示的内容')
-->
<h5>布尔类型</h5><br/>
${flag?c}<br/>
${flag?string}<br/>
${flag?string('yes','no')}<br/>
${flag?string('喜欢','不喜欢')}<br/>

${flag?then('yes','no')}<br/>
${flag?then('喜欢','不喜欢')}<br/>

2、日期类型

在Servlet中设置日期类型的数据

package com.xxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 *  @author: liman
 *  @Date: 2020/12/18 15:46
 *  @Description: FreeMarker 数据类型
 */
@WebServlet("/f03")
public class FreeMarker03 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //日期类型
        req.setAttribute("createDate",new Date());

        //请求转发跳转到指定的模板页面 template/f02.ftl
        req.getRequestDispatcher("template/f03.ftl").forward(req,resp);

    }
}

在webapp的template文件下面创建f03.ftl文件获取数据

<#--
    数据类型:日期类型
        在freemarker中日期类型不能直接输出:如果输出要先转成日期型或字符串
        1.年月日   ?date
        2.时分秒   ?time
        3.年月日时分秒 ?datetime
        4.指定格式   ?string ("自定义格式")
                    y: 年 M:月 d:日
                    H: 时 m:分 s:秒
-->

<#-- 输出日期格式 -->
    ${createDate?date} <br/>
<#-- 输出时间格式 -->
    ${createDate?time}<br/>
<#-- 输出日期时间格式 -->
    ${createDate?datetime} <br/>
<#-- 输出格式化日期格式 -->
    ${createDate?string("yyyy年MM月dd日 HH:mm:ss")}<br/>

3、数值类型

在Servlet中设置数值类型的数据

package com.xxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 *  @author: liman
 *  @Date: 2020/12/18 15:46
 *  @Description: FreeMarker 数据类型
 */
@WebServlet("/f04")
public class FreeMarker04 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //数值类型
        req.setAttribute("age",18);//数值型
        req.setAttribute("salary",10000);//数值型
        req.setAttribute("avg",0.545);//浮点型

        //请求转发跳转到指定的模板页面 template/f01.ftl
        req.getRequestDispatcher("template/f04.ftl").forward(req,resp);

    }
}

在webapp的template文件下面创建f04.ftl文件获取数据

<#--
    数据类型:数值类型
        在freemarker中数值类型可以直接输出;
        1.转字符串
          普通字符串   ?c
          货币型字符串  ?string.currency
          百分比型字符串 ?string.percent
         2.保留浮点型数值指定小数位(#表示一个小数位)
          ?string["0.##"
-->
<#-- 直接输出数值型 -->
${age} <br/>
${salary} <br/>
${avg} <br/>

<#-- 将数值转换成字符串类型 -->
${salary?c} <br/>

<#-- 将数值转化成货币类型字符串 -->
${salary?string.currency} <br/>

<#-- 将数值转化成百分比类型的字符串 -->
${avg?string.percent} <br/>

<#-- 将浮点型的数值转换成指定小数位输出(四舍五入) -->
${avg?string["0.##"]} <br/>

4、字符串类型

在Servlet中设置字符串类型的数据

package com.xxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 *  @author: liman
 *  @Date: 2020/12/18 15:46
 *  @Description: FreeMarker 数据类型
 */
@WebServlet("/f05")
public class FreeMarker05 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //字符串类型
        req.setAttribute("msg","Hello");
        req.setAttribute("msg2","freemarker");

        //请求转发跳转到指定的模板页面 template/f01.ftl
        req.getRequestDispatcher("template/f05.ftl").forward(req,resp);

    }
}

在webapp的template文件下面创建f05.ftl文件获取数据

<#--
    数据类型:字符串类型
        在freemarker中字符串类型可以直接输出:
        1.截取字符串(左闭右开)?substring(start,end)
        2.首字母小写输出 ?uncap_first
        3.首字母大写输出 ?cap_first
        4.字母转小写输出 ?lower_case
        5.字母转大写输出 ?upper_case
        6.获取字符串长度 ?length
        7.是否以指定字符开头(boolean 类型) ?starts_with("xx")?string
        8.是否以指定字符结尾(boolean 类型) ?ends_with("xx")?string
        9.获取指定字符的索引 ?index_of("xx")
        10.去除字符串前后空格 ?trim
        11.替换指定字符串 ?replace("xx","xx")
-->

${msg} -- ${msg2} <br/>
${msg?string} -- ${msg2?string} <br/>
<#--1.截取字符串(左闭右开)?substring(start,end)-->
${msg?substring(0,2)}<br/>
<#--2.首字母小写输出 ?uncap_first-->
${msg?uncap_first}<br/>
<#--3.首字母大写输出 ?cap_first-->
${msg?cap_first}<br/>
<#--4.字母转小写输出 ?lower_case-->
${msg?lower_case}<br/>
<#--5.字母转大写输出 ?upper_case-->
${msg2?upper_case}<br/>
<#--6.获取字符串长度 ?length-->
${msg?length}<br/>
<#--7.是否以指定字符开头(boolean 类型) ?starts_with("xx")?string-->
${msg?starts_with("a")?string}<br/>
<#--8.是否以指定字符结尾(boolean 类型) ?ends_with("xx")?string-->
${msg?ends_with("o")?string}<br/>
<#--9.获取指定字符的索引 ?index_of("xx")-->
${msg2?index_of("m")}<br/>
<#--10.去除字符串前后空格 ?trim-->
${msg2?trim}<br/>
<#--11.替换指定字符串 ?replace("xx","xx")-->
${msg?replace("he","we")}<br/>

空值类型:

在Servlet中设置空值类型的数据

package com.xxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 *  @author: liman
 *  @Date: 2020/12/18 15:46
 *  @Description: FreeMarker 数据类型
 */
@WebServlet("/f06")
public class FreeMarker06 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //空值类型
        req.setAttribute("str1",null);
        req.setAttribute("str2","");

        //请求转发跳转到指定的模板页面 template/f01.ftl
        req.getRequestDispatcher("template/f06.ftl").forward(req,resp);

    }
}

在webapp的template文件下面创建f05.ftl文件获取数据

<#--
字符串空值情况处理:

        FreeMarker的变量必须赋值,否则就会抛出异常。而对于FreeMarker来说,null值和不存在的变量是完全一样的,因为FreeMarker无法理解null值。

        FreeMarker提供两个运算符来避免空值:

①!:指定缺失变量的默认值

    ${value!}:如果value值为空,则默认值是空字符串

    ${value!"默认值"}:如果value值为空,则默认值是字符串“默认值”

②??:判断变量是否存在

    如果变量存在,返回true,否则返回false

    ${(value??)?string}

-->



<#-- 如果值不存在,直接输出会报错 -->
<#-- ${bb}-->

<#-- 值为null的数据 -->
<#--${str1}<br/>-->

<#-- 值为空字符串的数据 -->
${str2}<br/>
<#-- 使用!,当值不存在时,默认显示空字符串 -->
${str!}<br/>
<#-- 使用!"xx",当值不存在时,默认显示指定字符串 -->
${str!"这是一个默认值"}<br/>
<#-- 使用??,判断字符串是否为空;返回布尔类型,如果想要输出,需要将布尔类型转换成字符串-->
${(str??)?string}<br/>

5、sequence类型

在Servlet中设置sequence类型的数据

package com.xxx.servlet;

import com.xxx.entity.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.*;

/**
 *  @author: liman
 *  @Date: 2020/12/18 15:46
 *  @Description: FreeMarker 数据类型
 */
@WebServlet("/f07")
public class FreeMarker07_Sequence extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //序列类型 (数组、List、Set)
        //数组操作
        String[] stars = new String[]{"周杰伦","林俊杰","陈奕迅","五月天"};
        req.setAttribute("stars",stars);

        //List操作
        List<String> citys = Arrays.asList("上海","北京","杭州","深圳");
        req.setAttribute("cityList",citys);

        //JavaBean集合
        List<User> userList = new ArrayList<>();
        userList.add(new User(1,"zhangsan",22));
        userList.add(new User(2,"lisi",18));
        userList.add(new User(3,"wangwu",20));
        req.setAttribute("userList",userList);


        //请求转发跳转到指定的模板页面 template/f01.ftl
        req.getRequestDispatcher("template/f07.ftl").forward(req,resp);

    }
}

在webapp的template文件下面创建f05.ftl文件获取数据

<#--
    FreeMarker 数据类型
        序列类型 (数组、List、Set)
        通过list指令输出序列
        <#list 序列名 as 元素名>
            ${元素名}
        </#list>

        获取序列的长度        ${序列名?size}
        获取序列元素的下标     ${元素名?index}
        获取第一个元素        ${序列名?first}
        获取最后一个元素       ${序列名?last}


        倒序输出    序列名?reverse
        升序输出    序列名?sort
        降序输出    序列名?sort?reverse
        指定字段名排序   序列名?sort_by("字段名")
    注:一般是JavaBean集合,对应的字段名需要提供get方法
-->

<#-- 数组操作 -->
<#list stars as star>
    下标:${star?index}-姓名:${star}<br/>
</#list>

获取序列的长度:  ${stars?size}<br/>
获取第一个元素:   ${stars?first}<br/>
获取最后一个元素:  ${stars?last}<br/>

<#-- List操作 -->
<#list cityList as city>
    ${city}-
</#list>
<br/>
<#--倒序输出    序列名?reverse-->
<#list cityList?reverse as city>
    ${city}-
</#list>
<br/>
<#--升序输出    序列名?sort-->
<#list cityList?sort as city>
    ${city}-
</#list>
<br/>
<#--降序输出    序列名?sort?reverse-->
<#list cityList?sort?reverse as city>
    ${city}-
</#list>
<br/>

<#list userList as user>
    编号:${user.id}&nbsp;姓名:${user.username}&nbsp;${user.age}<br/>
</#list>

<#--指定字段名排序   序列名?sort_by("字段名")-->
<#list userList?sort_by("age") as user>
    编号:${user.id}&nbsp;姓名:${user.username}&nbsp;${user.age}<br/>
</#list>

6、Hash类型

在Servlet中设置Map类型的数据 

package com.xxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @author: liman
 * @Date: 2020/12/18 15:46
 * @Description: FreeMarker 数据类型
 */
@WebServlet("/f08")
public class FreeMarker08_Hash extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //Map操作
        Map<String, String> cityMap = new HashMap<>();
        cityMap.put("sh", "上海");
        cityMap.put("bj", "北京");
        cityMap.put("sz", "深圳");
        req.setAttribute("cityMap", cityMap);

        //请求转发跳转到指定的模板页面 template/f01.ftl
        req.getRequestDispatcher("template/f08.ftl").forward(req, resp);

    }
}

在webapp的template文件下面创建f06.ftl文件获取数据

<#--
    数据类型:hash类型
        key遍历输出
            <#list hash?keys as key>
                ${key} -- ${hash[key]}
            </#list>
         value遍历输出
            <#list hash?values as value>
                ${value}
            </#list>
-->
<#-- key遍历输出 -->
<#list cityMap?keys as key>
    ${key} -- ${cityMap[key]} <br/>
</#list>

<#--value遍历输出-->
<#list cityMap?values as value>
    ${value}<br/>
</#list>

       

 

猜你喜欢

转载自blog.csdn.net/LOVE_Me__/article/details/110352889