FreeMarker

目录

FreeMarker概述

FreeMarker概念

FreeMarker特性

        通用目标

        强大的模板语言

        通用数据模型

        为Web准备

        智能的国际化和本地化

        强大的XML处理能力

 FreeMarker环境搭建

        新建Maven Web项目

        配置坐标依赖和部署插件

        修改配置文件web.xml

        编写Servlet类

        新建模板文件ftl

        启动项目

        访问项目

FreeMarker注释和语法

FreeMarker的数据类型

布尔类型

日期类型

数值类型

字符串类型

字符串空值情况处理

sequence类型

hash类型

Freemarker常用指令

        assign自定义变量指令

        if elseif else逻辑判断指令

        list遍历指令

        marco自定义指令

        nested占位指令

        import 导入指令

        include包含指令

FreeMarker页面静态化

FreeMaker运算符

        算术运算符

        字符串运算

        逻辑运算符

        比较运算符 

        空值运算符 


FreeMarker概述


FreeMarker概念

        FreeMarker是一款模板引擎:即一种基于模板和要改变的数据,并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。是一个Java类库
        
        FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序,将视图从业务逻辑中抽离处理,业务中不再包括视图的展示,而是将视图交给FreeMarker 来输出。虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据。
        

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

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

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

        FreeMarker参考手册    http://freemarker.foofun.cn/

FreeMarker特性

   
        通用目标

        能够生成各种文本:HTML、XML、RTF、Java源代码等等
        易于嵌入到你的产品中:轻量级;不需要Servlet环境
        插件式模板载入器:可以从任何源载入模板,如本地文件、数据库等等
        你可以按你所需生成文本:保存到本地文件;作为Email 发送;从Web应用程序发送它返回给Web浏览器

        强大的模板语言

        所有常用的指令: include、if/elseif/else、循环结构
        在模板中创建和改变变量
        几乎在任何地方都可以使用复杂表达式来指定值
        命名的宏,可以具有位置参数和嵌套内容
        名字空间有助于建立和维护可重用的宏库,或将大工程分成模块,而不必担心名字冲突
        输出转换块∶在嵌套模板片段生成输出时,转换HTML转义、压缩、语法高亮等等;你可以定义自己的转换

        通用数据模型

        FreeMarker不是直接反射到ava对象,Java对象通过插件式对象封装,以变量方式在模板中显示
        你可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等等),告诉模板开发者使用方法,使其不受技术细节的打扰

        为Web准备

        在模板语言中内建处理典型Web相关任务(如HTML转义)的结构
        能够集成到Model2 Web应用框架中作为JSP的替代
        支持JSP标记库
        为MVC模式设计:分离可视化设计和应用程序逻辑;分离页面设计员和程序员

        智能的国际化和本地化

        字符集智能化(内部使用UNICODE)
        数字格式本地化敏感
        日期和时间格式本地化敏感
        非US字符集可以用作标识(如变量名)
        多种不同语言的相同模板

        强大的XML处理能力

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


 FreeMarker环境搭建

        新建Maven Web项目

        配置坐标依赖和部署插件

        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>com.xxxx</groupId>
    <artifactId>freemarker</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>freemarker 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>freemarker</finalName>
        <!--
           插件地址:Tomcat
           http://tomcat.apache.org/maven-plugin-2.2/
           Jetty
           https://www.eclipse.org/jetty/documentation/current/jetty-maven-plugin.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>
    <display-name>Archetype Created Web Application</display-name>

    <!-- FreeMarker的servlet配置-->
    <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>

        编写Servlet类

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;

@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);
    }
}

        新建模板文件ftl

        启动项目

        访问项目

 


FreeMarker注释和语法

html 注释语法

        <!--        -->


浏览器中查看源码可见


freemarker注释语法

        <#--    -->


浏览器中查看源码不可见(开发中推荐使用)

freemarker语法

        1.在freemarker中,html所有标签均适用
        2. js、css均适用,语法一致


FreeMarker的数据类型

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

  • 布尔型:等价于Java的Boolean类型,不同的是不能直接输出,可转换为字符串输出
  • 日期型:等价于Java的Date类型,不同的是不能直接输出,需要转换成字符串再输出
  • 数值型:等价于Java中的int,float,double等数值类型
    • 有三种显示形式:数值型(默认)、货币型、百分比型
  • 字符型:等价于Java中的字符串,有很多内置函数
  • sequence类型:等价于Java中的数组,list,set等集合类型
  • hash类型:等价于Java中的Map类型


布尔类型

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

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

2.获取数据

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

<h5>布尔类型</h5>
<#--获取数据-->
${flag?c}<br>
${flag?string}<br>
${flag?string('yes','no')}<br>
${flag?string('是','否')}<br>

在freemarker页面中不能直接输出,如果要输出需要转换成字符串

        方式一:?c
        方式二:?string?string( '为true时显示的内容','为false时显示的内容')


日期类型

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

//日期类型
request.setAttribute("createDate" , new Date()};

2.获取数据

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


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


数值类型


1.在Servlet设置数值型的数据

//数值类型
request.setAttribute("age" ,18);//数值型
request.setAttribute("num" , 10000);//数值型
request.setAttribute("avg" ,5.5467);//浮点型


2.获取数据

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

在freemarker中数值类型可以直接输出;
        1.转字符串
                普通字符串                       ?c
                货币型字符串                   ?string.currency
                百分比型字符串                ?string.percent
        2.保留浮点型数值指定小数位(#表示一个小数位)
                ?string["0.##"]


字符串类型

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

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

2.获取数据

<h5>字符串类型</h5>
${msg}--${msg2}<br>
${msg?string}--${msg2?string}<br>
<#--截取字符串(左闭右开)-->
${msg?substring(0,2)}<br>
<#--首字母小写输出-->
${msg?uncap_first}<br>
<#--首字母大写输出-->
${msg2?cap_first}<br>
<#--字母转小写输出-->
${msg?lower_case}<br>
<#--字母转大写输出-->
${msg?upper_case}<br>
<#--获取字符串长度-->
${msg?length}<br>
<#--是否以指定字符开头(boolean类型)-->
${msg?starts_with("H")?string}<br>
<#--是否以指定字符结尾(boolean类型)-->
${msg?ends_with("ac")?string}<br>
<#--获取指定字符的索引-->
${msg?index_of("e")}<br>
<#--去除字符串前后空格-->
${msg?trim}<br>
<#--替换指定字符串-->
${msg?replace("He","we")}<br>

在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")


字符串空值情况处理

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

1.在Servlet中设置数据

//空数据
request.setAttribute("str1",null);
request.setAttribute("str2","");

 2.获取数据

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

FreeMarker 提供两个运算符来避免空值:
        ①!:指定缺失变量的默认值
            ${value!l}:如果value值为空,则默认值是空字符串
            ${value!"默认值"}:如果value值为空,则默认值是字符串"默认值"
        ②??:判断变量是否存在
            如果变量存在,返回true,否则返回false
            ${(value??)?string}


sequence类型

1.在Servlet中设置序列类型的数据

//序列类型(数组、List.set)
//数组操作
string[] stars = new string[]{"周杰伦", "林俊杰","陈奕迅", "五月天"};
		request.setAttribute("stars" ,stars);
		//List操作
		List<string> citys = Arrays.asList("上海"", "北京","杭州","深圳");
		request.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));
		request.setAttribute("userList",userList);

2.获取数据

通过list指令输出序列
            <#list 序列名 as 元素名>
                ${元素名}
            </#list>

        数组操作

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

        List操作
倒序输出                序列名?reverse
升序输出                序列名?sort
降序输出                序列名?sort?reverse

        JavaBean操作
指定字段名排序     序列名?sort_by("字段名")


    注:一般是JavaBean集合,对应的字段名需要提供get方法

<#--数组操作-->
<#list stars as star>
    获取序列元素的下标${star?index}<br>
    ${star}<br>
</#list>
获取序列的长度${stars?size}<br>
获取第一个元素${stars?first}<br>
获取最后一个元素${stars?last}<br>
<#--List操作-->
<#list cityList as city>
    ${city} -
</#list>
<br>
<#--倒序输出-->
倒序输出
<#list cityList?reverse as city>
    ${city} -
</#list>
<br>
<#--升序输出-->
升序输出
<#list cityList?sort as city>
    ${city} -
</#list>
<br>
<#--降序输出-->
降序输出
<#list cityList?sort?reverse as city>
    ${city} -
</#list>
<br>
<#--JavaBean-->
<#list userList as user>
    编号:${user.userId}&nbsp;姓名:${user.uname}&nbsp;年龄:${user.uage}<br>
</#list>
<br>
<#--指定字段名排序-->
<#list userList?sort_by("uage") as user>
    编号:${user.userId}&nbsp;姓名:${user.uname}&nbsp;年龄:${user.uage}<br>
</#list>
package com.xxxx.entity;

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;
    }


}

hash类型

1.在Servlet中设置hash类型的数据

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

2.获取数据

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} |
</#list>

Freemarker常用指令

        assign自定义变量指令

                使用assign指令你可以创建一个新的变量,或者替换一个已经存在的变量。

语法:

        <#assign变量名=值>
        <#assign变量名=值        变量名=值>(定义多个变量)

<#--定义单个变量-->
<#assign str="hello">
${str} <br>
<#--定义多个变量-->
<#assign num=1 names=["zhangsan" , "lisi" , "wangwu"] >
${num} -- ${names?join(",")}


        if elseif else逻辑判断指令

         可以使用if,elseif和else指令来条件判断是否满足某些条件。

                格式:
                        <#if condition>
                            ...
                        <#elseif condition2>
                            ...
                        <#elseif condition3>
                            ...
                        <#else>
                            ...
                        </#if>

                注:
                        1. condition,condition2等:将被计算成布尔值的表达式。
                        2. elseif和else指令是可选的。

<#--if elseif else逻辑判断指令-->
<#assign score=60>
<#if score lt 60>
    <h6>不及格</h6>
    <#elseif score == 60>
        <h6>及格</h6>
    <#elseif score gt 60 && score lt 80>
        <h6>良好</h6>
    <#else>
        <h6>优秀</h6>
</#if>
<#--判断数据是否存在-->
<#assign list="">
<#if list??>
    数据存在
    <#else >
        数据不存在
</#if>
<br>
<#if list2??>
    数据存在
<#else >
    数据不存在
</#if>


        list遍历指令

                可以使用list指令来对序列进行遍历。

    list指令

                格式1:
                        <#list sequence as item>

                        </#list>

                格式2:
                        <#list sequence as item>

                        <#else>
                               当没有选项时,执行else指令
                        </#list>

    注:
        1. else部分是可选的
        2. sequence:想要迭代的项,可以是序列或集合的表达式
        3. item:循环变量的名称
        4.当没有迭代项时,才使用else指令,可以输出一些特殊的内容而不只是空在那里

<#--list指令-->
<#assign users =["张三","李四","王五"]>
<#--遍历序列-->
<#list users as user>
    ${user} |
</#list>

<br>
<#--判断数据不为空,再执行遍历(如果序列不存在,直接遍历会报错)-->
<#if users2??>
    <#list users2 as user>
        ${user} |
    </#list>
</#if>
<#--当序列没有数据项时,使用默认信息-->
<#assign users3=[]>
<#list users3 as user>
    ${user} |
    <#else >
        用户数据不存在
</#list>



        marco自定义指令

                可以使用macro指令来自定义一些自定义指令。
 

macro自定义指令(宏)

        1.基本使用
                格式:
                            <#macro   指令名>
                                指令内容
                            </#macro>

                使用:
                            <@指令名></@指令名>

        2.有参数的自定义指令
                格式:
                            <#macro   指令名     参数名1   参数名2>
                                指令内容
                            </#macro>

        使用:
                            <@指令名    参数名1=参数值1    参数名2=参数值2></@指令名>

    注:
        1.指令可以被多次使用。
        2.自定义指令中可以包含字符串,也可包含内置指令        

<#--定义基本的自定义指令-->
<#macro address>
1999-2015 The FreeMarker Project. A17 rights reserved.
</#macro>
<#--使用自定义指令-->
<@address></@address>

<#macro address2>
    <h2>1999-2015 The FreeMarker Project. A17 rights reserved.</h2>
</#macro>
<#--可以重复使用-->
<@address2></@address2>
<@address2></@address2>
<@address2></@address2>

<#--自定义有参数的指令-->
<#macro queryUserByName uname>
    通过用户名查询用户对象 -${uname}
</#macro>

<@queryUserByName uname="admin"></@queryUserByName>
<br>
<#--多个参数-->
<#macro queryUserByName2 uname upwd>
    通过用户名查询用户对象 -${uname} -${upwd}
</#macro>

<@queryUserByName2 uname="admin" upwd="123456"></@queryUserByName2>

<hr>
<#--自定义指令中包含内置指令-->
<#macro cfb>
    <#list 1..9 as i>
        <#list 1..i as j>
            ${j}*${i}=${j*i}&nbsp;
        </#list>
        <br>
    </#list>
</#macro>
<@cfb></@cfb>
<@cfb></@cfb>
<hr>
<#--传入参数-->
<#macro cfb2 num>
    <#list 1..num as i>
        <#list 1..i as j>
            ${j}*${i}=${j*i}&nbsp;
        </#list>
        <br>
    </#list>
</#macro>
<@cfb2 num=6></@cfb2>



        nested占位指令

        nested指令执行自定义指令开始和结束标签中间的模板片段。嵌套的片段可以包含模板中任意合法的内容。

        <#nested>
        nested相当于占位符,一般结合macro指令一起使用。
        可以将自定义指令中的内容通过nested指令占位,当使用自定义指令时,会将占位内容显示。

<#macro test>
    这是一段文本!
    <#nested>
    <#nested>
</#macro>
<@test><h4>这是文本后面的内容!</h4></@test>



        import 导入指令

        import指令可以引入一个库。也就是说,它创建一个新的命名空间,然后在那个命名空间中执行给定路径的模板。可以使用引入的空间中的指令。

commons.ftl

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

test.ftl 

<#--导入命名空间-->
<#import "commons.ftl" as common>
<#--使用命名空间中的指令-->
<@common.cfb2 num=8></@common.cfb2>


        include包含指令

        可以使用include指令在你的模板中插入另外一个FreeMarker模板文件。被包含模板的输出格式是在include标签出现的位置插入的。被包含的文件和包含它的模板共享变量,就像是被复制粘贴进去的一样。

<#--包含指令(引入其他页面文件) include-->
<#--html文件-->
<#include "test.html">

<#--freemarker文件-->
<#include "test2.ftl">

<#--text文件-->
<#include "test.txt">

test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>FreeMarker的使用</h1>
</body>
</html>

test2.ftl

<h3>FreeMarker文件</h3>

test.txt

freemarker

FreeMarker页面静态化

        通过上述介绍可知Freemarker是一种基于模板的、用来生成输出文本的通用工具.所以我们必须要定制符合自己业务的模板,然后生成自己的 html页面。Freemarker是通过freemarker.template.Configuration这个对象对模板进行加载的(它也处理创建和缓存预解析模板的工作),然后我们通过getTemplate方法获得你想要的模板,有一点要记住freemarker.template.Configuration在你整个应用必须保证唯一实例。

 news.ftl

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

NewsServlet.java

package com.xxxx.servlet;

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

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.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@WebServlet("/news")
public class NewsServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) 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","越南新增8597例新冠确诊病例 南部地区“居家令”延长两周");
        map.put("source","环球网官方帐号");
        map.put("pubTime","2021年08月02日 11:13");
        map.put("content","海外网8月2日电根据越南卫生部1日公布的信息,越南新增新冠肺炎确诊病例8620例,其中,本土病例8597例,境外输入病例23例。越南总理下令,要求南部地区继续实施为期两周的封锁措施。\n" +
                "\n" +
                "据《越南青年报》报道,越南已累计确诊154306例,1306人死亡。南部疫情“震中”胡志明市新增确诊病例4052例,累计确诊病例为94295例。此外,平阳省报告了2179例,隆安省569例,同奈省425例,庆和省298例,巴地头顿省184例,西宁省102例,芹苴市100例。\n" +
                "\n" +
                "越南总理范明政7月31日下令,自8月1日起,要求南部19个省市地区继续实施为期两周的封锁措施。越南于7月17日发布命令,要求关闭非必要的企业和服务,禁止两人以上集会,人与人之间至少保持2米的距离,以及暂停公共交通。居民除了就医和在指定地点购买食物外,禁止外出。(海外网 李芳) ");

        //获取项目的根目录
        String basePath=request.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 fileWriter=new FileWriter(file);

        //生成html(将数据模型填充到模板中)
        try {
            template.process(map,fileWriter);
        } catch (TemplateException e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            fileWriter.flush();
            fileWriter.close();
        }

    }
}

FreeMaker运算符

        算术运算符

                +-*/%

<#assign a1 = 8 a2 = 2 >
${a1} + ${a2} = ${a1 + a2} <br/>
${a1} - ${a2} = ${a1 - a2} <br/>
${a1} * ${a2} = ${a1 * a2} <br/>
${a1} / ${a2} = ${a1 / a2} <br/>
${a1} % ${a2} = ${a1 % a2} <br/>


        字符串运算

${ "hello" +"," + "freemarker"}


        逻辑运算符

                &&||!


        比较运算符 

        > (gt):大于号,推荐使用gt
        < (lt):小于号,推荐使用lt
        >= (gte):大于等于,推荐使用gte
        <= (lte):小于等于,推荐使用lte
        == :等于
        != :不等于


        空值运算符 

        ??:判断是否为空,返回布尔类型
            如果不为空返回false,如果为空返回true,不能直接输出
                    ${(name??)?string}
        !:设置默认值,如果为空,则设置默认值
                    1.设置默认为空字符串:
                                ${name!}
                    2.设置指定默认值
                                ${name!'zhangsan'}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烟火9092

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值