FreeMarker详解

  • Post author:
  • Post category:其他




FreeMarker

http://freemarker.foofun.cn/



1.主要内容

image-20220427113842110



2.FreeMarker概述



2.1FreeMarker概念

image-20220427113835891

image-20220427113818706



2.2FreeMarker特性



2.2.1.通用目标

image-20220427113811003



2.2.2.强大的模板语言

image-20220427113806173



2.2.3.通用的数据模型

image-20220427113757675



2.2.4.为Web准备

image-20220427113752142



2.2.5.智能的国际化和本地化

image-20220427113738591



2.2.6.强大的XML处理能力

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WI5uFmS3-1651031146669)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220129100819859.png)]





2.3FreeMarker环境搭建



2.3.1.新建环境项目

pom.xml文件

<?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>org.example</groupId>
  <artifactId>ferrmarker</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>ferrmarker 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>
    <!-- freemarker的坐标依赖 -->
    <dependency>
      <groupId>org.freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>2.3.23</version>
    </dependency>
    <!-- servlet-api的坐标依赖 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
    </dependency>

  </dependencies>

  <build>
    <finalName>ferrmarker</finalName>
    <!--
			插件地址:
			Tomcat
				http://tomcat.apache.org/maven-plugin-2.2/
			Jetty
				https://www.eclipse.org/jetty/documentation/current/jetty-mavenplugin.
			html
	-->
    <plugins>
      <!-- 配置jetty插件 -->
      <plugin>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>9.2.1.v20140609</version>
      </plugin>
    </plugins>

  </build>
</project>

web.xml文件

<!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>
<!--  FreeMarker的servlet配置-->
  <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>
      <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>
<!--  处理所有以.ft结尾的文件;ftl是free marker默认的文件后缀-->
  <servlet-mapping>
    <servlet-name>freemarker</servlet-name>
    <url-pattern>*.ftl</url-pattern>
  </servlet-mapping>


</web-app>

运行成功

image-20220427113921241

跟着教程一步一步来就好了

https://www.bilibili.com/video/BV1jt4y1r7Lx?p=2

然后就是第一遍做没做出来,第二遍就好了呀

第一遍的问题

问题(1)

image-20220427113938158

工作名和组名那里要改正

问题(2)

image-20220427113955336

jetty:run -Djetty.port=9090

run后面是个空格然后才是-





3.FreeMarker的数据类型

image-20220427114001786



3.1布尔类型

image-20220427114008201

eg:FreeMarker.java文件

package com.xxxx.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 yanchaochao
 * @date 2022/1/29 19:40
 */
@WebServlet("/f02")
public class FreeMarker02 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置数据
        /*布尔类型*/
        req.setAttribute("flag",true);
        req.getRequestDispatcher("template/f02.ftl").forward(req,resp);
    }

f02.ftl文件

<h4>FreeMarker 数据类型</h4>

<#--
    FreeMarker 数据类型
    布尔书数据类型
        不能在FreeMarker直接输出,如果要输出需要转换成字符串
        方式一:?c
        方式二:?string或?string(‘为true显示的内容’,为false时显示的内容)
-->
<h5>布尔类型</h5>

${flag?c}<br>
${flag?string}<br>
${flag?string('yes','no')}<br>
${flag?string('俺喜欢','她不中')}<br>

image-20220427114018578

<#--
    FreeMarker 数据类型
    布尔书数据类型
        不能在FreeMarker直接输出,如果要输出需要转换成字符串
        方式一:?c
        方式二:?string或?string(‘为true显示的内容’,为false时显示的内容)
-->



3.2.日期类型

image-20220427114039563

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

-->

eg:FreeMarker.java文件

package com.xxxx.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 yanchaochao
 * @date 2022/1/29 19:40
 */
@WebServlet("/f02")
public class FreeMarker02 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置数据
        /*日期类型*/
        req.setAttribute("createDate",new Date());







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

f02.ftl文件

<h4>FreeMarker--数据类型</h4>

<h5>布尔类型</h5>
${flag?c}<br>
${flag?string}<br>
${flag?string('yes','no')}<br>
${flag?string('俺喜欢','她不中')}<br>
<#--、-->
<#---->
<#--
    FreeMarker 数据类型
    日期类型
        不能在FreeMarker日期类型中直接输出,如果要输出需要转换成日期型或字符串
        1.年月日:    ?date
        2.时分秒:    ?time
        3.年月日时分秒:    ?datetime
        4.自定义格式:    ?string(”自定义")
                        y年    M月    d日
                        H时    m分    s秒

-->
<h5>日期类型</h5>
${createDate?date}<br>
${createDate?time}<br>
${createDate?datetime}<br>
${createDate?string("yyy/MM/dd HH:mm:ss")}<br>

<#--根据自己的需求格式输出结果-->




3.3.数值类型

image-20220427114051829

eg:FreeMarker.java文件

  /*数值类型*/
        req.setAttribute("age",18);
        req.setAttribute("num",10000);
        req.setAttribute("avg",5.5467);

f02.ftl文件

<h5>数值类型</h5>
${age}<br>
${num}<br>
${avg}<br>
<#--将数值转化成字符串类型-->
${age?c}<br>
<#--将数值转化成货币类型-->
${num?string.currency}<br>
<#--将数值转化为百分比类型的字符串-->
${num?string.percent}<br>
<#--将浮点型的数值转化成指定小数输出-->
${avg?string["0.##"]}



3.4.字符串类型

image-20220427114104128

eg:FreeMarker.java文件

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

f02.ftl文件

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

image-20220427114111568



字符串空值情况处理

image-20220427114130454



3.5.sequence类型

image-20220427114138841

image-20220427114146025



1.数组

eg:FreeMarker.java文件

//数组
        String[] stars = new String[]{"周杰伦","林俊杰","五月天","陈奕迅"};
        req.setAttribute("stars",stars);

f02.ftl文件

<#--数组操作-->
<#list stars as stars>
    ${stars}<br>
</#list>
获取序列长度:${stars?size}<br>
获取第一个元素:${stars?first}<br>
获取最后一个元素:${stars?last}<br>
<hr>

image-20220427114153016



2.list

eg:FreeMarker.java文件

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

f02.ftl文件

<#--list操作-->
<#list cityList as city>
    ${city} -
</#list>


<hr>
<#--排序-->
<#--倒序输出-->
<#list cityList?reverse as city>
    ${city} -
</#list>
<hr>
<#--升序输出-->
<#list cityList?sort as city>
    ${city} -
</#list>
<hr>
<#--降序输出-->
<#list cityList?sort?reverse  as city>
    ${city} -
</#list>
<hr>
<hr>
<#list userList as user>
    编号:${user.userId}&nbsp;
    姓名:${user.uname}&nbsp;
    编号:${user.uage}&nbsp;
    <br>
</#list>
<hr>

image-20220427114159159



3.JavaBean的排序

eg:FreeMarker.java文件

 //JavaBean集合
        List<User> userList = new ArrayList<>();
        userList.add(new User(1,"张三",22));
        userList.add(new User(2,"李四",18));
        userList.add(new User(3,"王五",20));
        req.setAttribute("userList",userList);

User文件

package com.xxxx.servlet.entity;

/**
 * @author yanchaochao
 * @date 2022/1/30 1:43
 */
public class User {
    private Integer userId;
    private String uname;
    private Integer uage;

    public User() {
    }

    public User(Integer userId, String uname, Integer uage) {
        this.userId = userId;
        this.uname = uname;
        this.uage = uage;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public Integer getUage() {
        return uage;
    }

    public void setUage(Integer uage) {
        this.uage = uage;
    }
}

f02.ftl文件

<#--JavaBean的排序-->
<#list userList?sort_by("uage") as user>
    编号:${user.userId}&nbsp;
    姓名:${user.uname}&nbsp;
    编号:${user.uage}&nbsp;
    <br>
</#list>

image-20220427114206750



3.6hash类型

image-20220427114212425

eg:FreeMarker.java文件

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

f02.ftl文件

<#--Hash-->
<#list cityMap? keys as key>
    ${key}   - ${cityMap[key]}
</#list>
<br>
<#list cityMap? values as value>
    ${value}
</#list>
<br>



4.FreeMarker常见指令



4.1.assign自定义变量指令

image-20220427114231410

<#assign name1=value1 name2=value2 ... nameN=valueN>
或
<#assign same as above... in namespacehash>
或
<#assign name>
  capture this
</#assign>
或
<#assign name in namespacehash>
  capture this
</#assign>



4.2.if, else, elseif

image-20220427114239511

eg:FreeMarker03.java文件

package com.xxxx.servlet;

/**
 * @author yanchaochao
 * @date 2022/1/30 2:35
 */

import com.xxxx.servlet.entity.User;
import javax.net.ssl.ManagerFactoryParameters;
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.*;

@WebServlet("/f03")
public class FreeMarker03 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



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

f02.ftl文件

<#--if, else, elseif-->
        <#assign score=60>
        <#if score lt 60>
            <h6>你个小渣渣</h6>
            <#elseif score == 80>
                <h6>分不在高,及格就行</h6>
            <#elseif score gt 60 &&score lt 80 >
                <h6>革命尚未成功,同志仍需努力</h6>
            <#else >
            <h6>哎呦不错哦!</h6>
        </#if>
    <#--判断数据是否存在-->
    <#assign list="">
    <#if list??>
        数据存在
        <#else >
        数据不存在
    </#if>

image-20220427114251933



4.3.list指令

image-20220427114309610

image-20220427114320984

eg:FreeMarker03.java文件

package com.xxxx.servlet;

/**
 * @author yanchaochao
 * @date 2022/1/30 2:35
 */

import com.xxxx.servlet.entity.User;
import javax.net.ssl.ManagerFactoryParameters;
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.*;

@WebServlet("/f03")
public class FreeMarker03 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



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

f02.ftl文件

<#--list指令-->
    <hr>
    <#assign users = ["张三","李四","王五"]>
    <#list users as user>
    ${user} |
    </#list>
    <br>
    <#--判断数据不为空,再执行遍历(如果序列不存在,直接遍历会报错)-->
    <#if user2??>
        <#list users2 as user>
            ${user}
        </#list>
    </#if>
    <#assign users3=['a']>
    <#list users3 as user>
        ${user}
        <#else >
            用户数据不存在!
    </#list>

image-20220427114327534



4.4.macro自定义指令

image-20220427114334608

 <#--macro自定义指令-->
    <#macro address>
        这个就是自定义的指令
    </#macro>
        <#--使用自定义指令-->
        <@address></@address>
        <@address></@address>
        <@address></@address>
    <hr>
    <#--自定义有参数的指令-->
    <#macro queryUserByName uname>
    通过用户名查询用户对象-${uname}
    </#macro>
    <@queryUserByName uname="admin"></@queryUserByName>
    <hr>
    <#macro queryUserByName02 uname upwd phone>
        通过用户名查询用户对象-${uname}-${upwd}-${phone}
    </#macro>
    <@queryUserByName02 uname="张三" upwd= "123456" phone="666"></@queryUserByName02>

<hr>
<hr>
<#--做一个九九乘法表-->
<#macro cfb>
    <#list 1..9 as i>
        <#list 1..i as j>
            ${j} * ${i} = ${j*i} &nbsp;
        </#list>
        <br>
    </#list>
</#macro>
<@cfb></@cfb>


    <#--升级九九乘法表-->
    <#macro cfb02 num>
        <#list 1..num as i>
            <#list 1..i as j>
                ${j} * ${i} = ${j*i} &nbsp;
            </#list>
            <br>
        </#list>
    </#macro>
    <@cfb02 num=5></@cfb02>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lMLf9pry-1651031146676)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220427114342203.png)]



4.5.nested占位指令

image-20220427114351724

<#--占位指令-->

<#macro test>
    <#nested >
    <br>
    这是一段文本
    <#nested >
</#macro>
<@test>xxxxxxxxxx</@test>

image-20220427114358332



4.6.import导入指令

image-20220427114404601

eg:FreeMarker04.java文件

package com.xxxx.servlet;
/**
 * @author yanchaochao
 * @date 2022/1/30 11:24
 */
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("/f04")
public class FreeMarker04 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



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

f04.ftl文件

<#--通过import指令引入命令空间-->
<#--引用f03文件中的-->
<#import "f03.ftl" as f3>
<@f3.cfb></@f3.cfb>
<hr>
<#--设置一个通用文件调用-->
<#import "commons.ftl" as cm>
<@cm.cfb02 num =5></@cm.cfb02>

commons.ftl文件

<#macro cfb02 num>
    <#list 1..num as i>
        <#list 1..i as j>
            ${j} * ${i} = ${j*i} &nbsp;
        </#list>
        <br>
    </#list>
</#macro>
<@cfb02 num=5></@cfb02>

image-20220427114412311



4.7.include包含指令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-661DSqmn-1651031146677)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220427114420811.png)]

f04.ftl文件

<#--包含指令-->
<#--html文件-->
<#include "tset.html">

tset.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>包含</title>
</head>
<body>
Hello
</body>
</html>




5.FreeMarker页面静态化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3laUZsDo-1651031146677)(FreeMarker.assets/image-20220130114432562.png)]



5.1.定义模板

image-20220427114430690



5.2加载模板

NewsServlet.java文件

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yanchaochao
 * @date 2022/1/30 11:50
 */
@WebServlet("/news")
public class NewsServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //实例化模板对象
        Configuration configuration = new Configuration();
        //设置加载模板的上下文 以及模板的加载路径(模板的存放路径)
        configuration.setServletContextForTemplateLoading(getServletContext(), "/template");
        //设置模板的编码格式
        configuration.setDefaultEncoding("UTF-8");
        //加载模板文件 获取模板对象
        Template template = configuration.getTemplate("news.ftl");
        //设置数据模型
        Map<String, Object> map = new HashMap<>();
        map.put("title", "国务院联防联控机制:坚决防止春节返乡政策“一刀切”");
        map.put("source", "光明网-《光明日报》");
        map.put("pubTime", "2022-01-30 03:41");
        map.put("content", "春节将至,一些群众返乡遇阻引发社会关注,国家卫健委新闻发言人米锋在1月29日国务院联防联控机制举行的发布会上表示,国务院联防联控机制综合组已进行核实,并及时反馈地方,要求立即整改,坚决防止返乡政策“简单化一刀切,让广大群众度过一个健康、欢乐、祥和的春节。");
        //获取项目的根目录
        String basePath = req.getServletContext().getRealPath("/");
        //设置html的存放路径
        File htmlFile = new File(basePath + "/html");
        //判断文件(目录)是否存在
        if (!htmlFile.exists()) {
            //如果文件目录不存在,则新建文件目录
            htmlFile.mkdir();
        }
        //得到生成的文件名(生成随机不重复的文件名)
        String fileName = System.currentTimeMillis() + ".html";
        //创建html文件
        File file = new File(htmlFile, fileName);
        //获取文件输出流
        FileWriter writer = new FileWriter(file);
        //生成html(将数据模型填充到模板中)
        try {
            template.process(map, writer);
        } catch (TemplateException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            writer.flush();
            writer.close();
        }
    }
}

new.ftl

<!DOCTYPE html>
<html>
<head>
    <#--freemarker模板中设置编码格式,否则中文有可能乱码-->
    <meta http-equiv="content-type" content="text/html;charset=UTF-8">
</head>
<body>
<#--新闻标题-->
<h2 align="center">${title}</h2>
<#--新闻来源和发布时间-->
<p align="center">
    新闻来源:${source}&nbsp;&nbsp;
    发布时间:${pubTime}
</p>
<#--新闻内容-->
<p style="text-indent: 2em">
    ${content}
</p>
</body>
</html>

先运行

http://localhost:9090/news

image-20220427114441860

然后会在webapp中生成1643517894900.html

image-20220427114452719

再次访问

http://localhost:9090/html/1643517894900.html

image-20220427114502039



6.FreeMarker运算符



6.1.算术运算符

image-20220427114508096



6.2.逻辑运算符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r4oSQWsc-1651031146679)(FreeMarker.assets/image-20220130124022134.png)]



6.3.比较运算符

image-20220427114514088



6.4.控制运算符

image-20220427114525172



版权声明:本文为m0_63324772原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。