总结59 FreeMarker 前端页面静态化

补充:集成于Spring

一.在resources目录下创建ftl路径引用文件

文件名为freemarker.properties

out_put_path=D:/IdeaProjects/czjk_parent/health_parent/health_mobile/src/main/webapp/pages

二.创建在Spring配置文件中添加集成配置

此处以provider的’spring-service.xml’为例子
要添加到配置文件中的内容:

   <bean id="freemarkerConfig"
          class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <!--指定模板文件所在目录-->
        <property name="templateLoaderPath" value="/WEB-INF/ftl/" />
        <!--指定字符集-->
        <property name="defaultEncoding" value="UTF-8" />
         <property name="freemarkerSettings">
        <props>
            <!--用于解决前端报空指针问题-->
            <prop key="classic_compatible">true</prop>
        </props>
    </property>
    </bean>

    <!--加载属性文件,后期在java代码中会使用到属性文件中定义的key和value-->
    <context:property-placeholder location="classpath:freemarker.properties"/>

集成后的全部内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/mvc
                            http://www.springframework.org/schema/mvc/spring-mvc.xsd
                            http://code.alibabatech.com/schema/dubbo
                            http://code.alibabatech.com/schema/dubbo/dubbo.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 指定应用名称 -->
    <dubbo:application name="health_service_provider"/>
    <!--指定暴露服务的端口,如果不指定默认为20880-->
    <dubbo:protocol name="dubbo" port="20887"/>
    <!--指定服务注册中心地址-->
    <dubbo:registry address="zookeeper://localhost:21321"/>
    <!--批量扫描,发布服务-->
    <dubbo:annotation package="cn.health.service"/>


    <bean id="freemarkerConfig"
          class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <!--指定模板文件所在目录-->
        <property name="templateLoaderPath" value="/WEB-INF/ftl/" />
        <!--指定字符集-->
        <property name="defaultEncoding" value="UTF-8" />
        <property name="freemarkerSettings">
            <props>
                <!--用于解决前端报空指针问题-->
                <prop key="classic_compatible">true</prop>
            </props>
        </property>
    </bean>

    <!--加载属性文件,后期在java代码中会使用到属性文件中定义的key和value-->
    <context:property-placeholder location="classpath:freemarker.properties"/>




</beans>

中文路径,注意编码格式:

<context:property-placeholder location="classpath:freemarker.properties" file-encoding="UTF-8"/>

注意,如果有多个property-placeholder,只能写在一个地方,同时用逗号进行分隔:

<context:property-placeholder location="classpath:freemarker.properties,classpath:redis.properties" file-encoding="UTF-8"/>

三.在Java类中引用FreeMarker的Spring集成对象

在这里插入图片描述

Freemarker介绍

FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与 Web 容
器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还
可以用于生成 XML,JSP 或 Java 等。

模板

模板文件中有四种元素:
1、文本,直接输出的部分

2、注释,即<#–…-->格式不会输出

3、插值(Interpolation):即${…}部分,
将使用数据模型中的部分替代输出

4、FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出

Freemarker的模板文件后缀可以任意,一般建议为ftl
补充资料

模板引擎总结(Thymeleaf,FreeMarker,Enjoy,Velocity,JSP等)

https://www.cnblogs.com/ywb-articles/p/10627398.html

准备工作

一.导入依赖Jar包

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>

定义模板

定义FTL文件模板

以下模板为示例模板,仅供参考
Freemarker的模板文件后缀可以任意,一般建议为ftl

<html>
<head>
<meta charset="utf-8">
<title>Freemarker入门</title>
</head>
<body>
<#--我只是一个注释,我不会有任何输出 -->
${name}你好,${message}
</body>
</html>

定义Java代码模板

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

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class FreeMarkerTest {

    public static void main(String[] args) throws IOException, TemplateException {
        //创建freemarker的配置对象
        Configuration configurationObj = new Configuration(Configuration.getVersion());
        //设置模板文件所在目录
        configurationObj.setDirectoryForTemplateLoading(new File("D:\\freemarker"));
        //设置字符集
        configurationObj.setDefaultEncoding("utf-8");

        //加载模板文件,代码将会应用到该模板HTML的ftl格式文件中(格式必须为ftl,最好用Notepate++将文件编码设置为UTF-8无BOM编码格式)
        Template templateObj = configurationObj.getTemplate("index.ftl");

        //准备所需要给模板文件传递的数据,通常是由HashMap来封装传递.你也可以使用实体类进行封装传递
        Map hashMapObj = new HashMap();

        //定义要给前端传递的数据键值对
        hashMapObj.put("paramname","你好,世界!Hello world" );
        hashMapObj.put("password","abc123456" );

        //定义输出流 输入一个用于输出成品FreeMarker的静态页面文件绝对路径,静态页面的格式必须为Html
        Writer writeObj = new FileWriter("D:\\freemarker\\test.html");

        //开启输出流,将成品FreeMarker作为静态页面文件进行输出
        templateObj.process(hashMapObj,writeObj );


        //关闭输出流
        writeObj.close();



    }

}

assign指令语法

变量引用语法

assign指令用于在页面上定义一个变量

<#assign linkman="周先生">
联系人:${linkman}

<#assign testname="这里是练习assign指令的语法!">
assign简单指令练习,文本内容为:${testname}

对象(Json)引用语法

经常要复用和修改的内容,就可以在页面上定义变量,这样未来只需要调整变量内容即可

<#assign info={"mobile":"13812345678",'address':'北京市昌平区'} >
电话:${info.mobile} 地址:${info.address}

<#assign objparam={"name":"研一","age":"24","address":"中国北京"}>
assign之对象数据类型引用,姓名为:${objparam.name} 年龄为:${objparam.age} 地址为:${objparam.address}

include指令

include指令用于模板文件的嵌套,即:用于导入其它ftl模板文件.类似于Js中可以导入其它js文件一样.

(1)创建模板文件head.ftl

<h1>黑马程序员</h1>

(2)修改入门案例中的test.ftl,在test.ftl模板文件中使用include指令引入上面的模板文件

<#include "head.ftl"/>

判断指令

if指令用于判断

用法一:直接判断布尔值

(1)在模板文件中使用if指令进行判断

<#--<#assign success=true>--
<#if success=true>
你已通过实名认证
<#else>
你未通过实名认证
</#if>

(2)在java代码中为success变量赋值

map.put("success", true);

在freemarker的判断中,可以使用= 也可以使用==

用法二:判断数据内容(如字符串,数值)

<#if password="abc123456">
密码正确,通过验证!
<#else>
密码错误,无法通过验证!
</#if>

用法三:判断某变量是否存在

OR.双问号’??'判断法

在这里插入图片描述
判断某变量是否存在使用 “??”
用法为:变量名??,如果该变量存在,返回true,否则返回false

OR.感叹号’!'文本替换法

如果变量不存在,则代替变量充填为其它内容.
普通变量用法:
例一: ${name!''}
解释:表示如果name为空,显示空字符串。
例二: ${name!'你好!'}
解释:表示如果name为空,显示’你好’字符串。

嵌套对象用法:
例一: ${(stu.bestFriend.name)!''}
如果stu或bestFriend或name为空,默认显示空字符串。

if指令补充说明

	<#assign success=false>
	<#if success=true>
	  你已通过实名认证
	<#else>  
	  你未通过实名认证
	</#if>

如果JAVA代码和模板文件中都有变量,以模板文件中为主

else-if的用法:

<#if success=='0'>
男性
<#elseif  success=='1'>
女性
<#else>
 未知性别
</#if>

list指令之遍历List集合

很简单,用于遍历输出list集合中的数据.

范例一

ftl文件代码如下:

<#list goodsList as goods>
	  商品名称: ${goods.name} 价格:${goods.price}<br>
	</#list>

java代码如下:

  List goodsList=new ArrayList();

        Map goods1=new HashMap();
        goods1.put("name", "苹果");
        goods1.put("price", 5.8);

        Map goods2=new HashMap();
        goods2.put("name", "香蕉");
        goods2.put("price", 2.5);

        Map goods3=new HashMap();
        goods3.put("name", "橘子");
        goods3.put("price", 3.2);

        goodsList.add(goods1);
        goodsList.add(goods2);
        goodsList.add(goods3);

        map.put("goodsList", goodsList);

范例二

ftl代码文件如下:

<#list arraylist as forname>
姓名:${forname.name} 年龄:${forname.age} 地址:${forname.address} <br>
</#list>

java代码如下:

  Map hashMapObj = new HashMap();

        ObjectForArrayList obj1 = new ObjectForArrayList("张三","15","北京");
        ObjectForArrayList obj2 = new ObjectForArrayList("李四","18","南京");
        ObjectForArrayList obj3 = new ObjectForArrayList("王五","21","东京");
        ArrayList<ObjectForArrayList> arrayObj = new ArrayList<>();
        arrayObj.add(obj1);
        arrayObj.add(obj2);
        arrayObj.add(obj3);
        hashMapObj.put("arraylist",arrayObj );

list指令之遍历Map集合

在这里插入图片描述

java代码如下:

@Controller
@RequestMapping("/freemarker")
public class FreemarkerController {
    @Autowired
    RestTemplate restTemplate;

    @RequestMapping("/test1")
    public String freemarker(Map<String, Object> map){
        Student studentOne = new Student();
        studentOne.setName("张留章");
        studentOne.setAge(25);
        studentOne.setBirthday(null);
        studentOne.setMoney(1000000.0F);

        Student studentTwo = new Student();
        studentTwo.setName("张仕聪");
        studentTwo.setAge(24);
        studentTwo.setBirthday(null);
        studentTwo.setMoney(1000000.0F);


        Map<String,Student> mapForStudent = new HashMap<>();
        mapForStudent.put("studentOne",studentOne );
        mapForStudent.put("studentTwo",studentTwo );


        map.put("mapForStudent", mapForStudent);
        //返回模板文件名称 即:返回给templates目录下的'test1'.ftl
        return "test1";
    }
}

ftl文件代码如下:

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

<h2>遍历Map集合中的学生对象信息</h2><br>
其中的'key'为别名.
<#list mapForStudent?keys as key>

${mapForStudent[key].name}<br>
${mapForStudent[key].age}<br>
${mapForStudent[key].money}<br>


</#list>


</body>
</html>

内建函数

一.显示集合长度

格式:${集合变量名?size}

二.显示日期

能够将Date对象转为字符串日期显示在页面.

显示年月日: ${日期变量名?date}
显示时分秒:${日期变量名?time}
显示日期+时间:${日期变量名?datetime}
自定义格式化:${日期变量名?string("yyyy年MM月")
在这里插入图片描述

Freemarker静态化步骤模板参考示例

基于模板文件来实现静态化

/基于模板生成静态化文件
@Test
public void testGenerateHtml() throws IOException, TemplateException {
//创建配置类
Configuration configuration=new Configuration(Configuration.getVersion());

//设置模板路径
String classpath = this.getClass().getResource("/").getPath();
configuration.setDirectoryForTemplateLoading(new File(classpath + "/templates/"));
//设置字符集
configuration.setDefaultEncoding("utf‐8");
//加载模板
Template template = configuration.getTemplate("test1.ftl");
//数据模型
Map<String,Object> map = new HashMap<>();
map.put("name","黑马程序员");
//静态化
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
//静态化内容
System.out.println(content);
InputStream inputStream = IOUtils.toInputStream(content);
//输出文件
FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/test1.html"));
int copy = IOUtils.copy(inputStream, fileOutputStream);
}

基于字符串来实现静态化

//基于模板字符串生成静态化文件
@Test
public void testGenerateHtmlByString() throws IOException, TemplateException {
    //创建配置类
    Configuration configuration=new Configuration(Configuration.getVersion());
    //模板内容,这里测试时使用简单的字符串作为模板
    String templateString="" +
    "<html>\n" +
    " <head></head>\n" +
    " <body>\n" +
    " 名称:${name}\n" +
    " </body>\n" +
    "</html>";
    //模板加载器
    StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
    stringTemplateLoader.putTemplate("template",templateString);
    configuration.setTemplateLoader(stringTemplateLoader);
    //得到模板
    Template template = configuration.getTemplate("template","utf‐8");
    //数据模型
    Map<String,Object> map = new HashMap<>();
    map.put("name","黑马程序员");
    //静态化
    String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
    //静态化内容
    System.out.println(content);
    InputStream inputStream = IOUtils.toInputStream(content);
    //输出文件
    FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/test1.html"));
    IOUtils.copy(inputStream, fileOutputStream);
}

Freemarker真实应用代码

用到三个需要注入的成员变量

        model 用于获取到存储在Mongodb的‘dataUrl'的内容
        如:
        {"id":"5a791725dd573c3574ee333f","name":"轮播图","model":[{"key":"banner1","name":"轮播图1地址","url":null,"mapValue":null,"value":"http://www.xuecheng.com/img/widget-bannerB.jpg"},{"key":"banner2","name":"轮播图2地址","url":null,"mapValue":null,"value":"http://www.xuecheng.com/img/widget-bannerA.jpg"},{"key":"banner3","name":"轮播图3地址","url":null,"mapValue":null,"value":"http://www.xuecheng.com/img/widget-banner3.png"}]}

        template 真的就是用于获取模板,也就是模板html代码。

        思路就是将model(dataUrl链接里头请求到的参数内容),填充至template的Html代码里头。
 */
 //用于将请求到的内容直接以字符串的形式返回给前端(应用于Freemarker页面静态化)
    @Autowired
    RestTemplate restTemplateObj;

    @Autowired
    GridFsTemplate gridFsTemplateObj;

    @Autowired
    GridFSBucket gridFSBucketObj;
 //静态化
    public String getPageHtml(String pageId){
        //获取数据模型
        Map model = this.getModelByPageId(pageId);
        if (model==null){
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAISNULL);

        }

        //获取模板
        String templateByPageId = this.getTemplateByPageId(pageId);
            //判断是否为空
        if (StringUtils.isEmpty(templateByPageId)){

            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
        }

        //执行静态化
        String s = this.genereteHtml(templateByPageId, model);
        return s;

    }

    //获取模型数据
    private Map getModelByPageId(String pageId){
        //取出页面的信息
        CmsPage cmsPageObj = getById(pageId);
        if (cmsPageObj==null){

            ExceptionCast.cast(CmsCode.CMS_PAGE_NOTEXISTS);

        }


        //判断是否存在dataUrl
        String dataUrl = cmsPageObj.getDataUrl();
        if (StringUtils.isEmpty(dataUrl)){//如果为空

            //不存在则触发可预知异常
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAURLISNULL);

        }

        ResponseEntity<Map> forEntity = restTemplateObj.getForEntity(dataUrl,Map.class );

        Map body = forEntity.getBody();

        return body;
    }

    //获取页面模板
    private String getTemplateByPageId(String pageId){

        CmsPage cmsPage = this.getById(pageId);
        if (cmsPage==null){
            ExceptionCast.cast(CmsCode.CMS_PAGE_NOTEXISTS);
        }

        //判断页面模板是否为空
        String templateId = cmsPage.getTemplateId();
        if (StringUtils.isEmpty(templateId)){
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
        }

        //根据模板Id查询模板集合,获取模板信息
        Optional<CmsTemplate> optionalObj = cmsTemplateRepositoryObj.findById(templateId);
        if (optionalObj.isPresent()){
            CmsTemplate cmsTemplate = optionalObj.get();
            //根据模板id获取文件id(templateFileId)
            String templateFileId = cmsTemplate.getTemplateFileId();


            //根据模板文件id来取出文件内容 //此处Query.query所查询的集合是fs.files
            GridFSFile gridFSFileObj = gridFsTemplateObj.findOne(Query.query(Criteria.where("_id").is(templateFileId)));

//打开一个下载流
            GridFSDownloadStream gridFSDownloadStreamObj = gridFSBucketObj.openDownloadStream(gridFSFileObj.getObjectId());

            //创建GridFsResource
            GridFsResource gridFsResource = new GridFsResource(gridFSFileObj,gridFSDownloadStreamObj );

            try{

                String content = IOUtils.toString(gridFsResource.getInputStream());

                return content;//将获取到的模板内容(即html代码)返回
            }catch (Exception e){
                e.printStackTrace();
            }



        }



        return null;
    }

    //执行静态化
    private String genereteHtml(String template,Map model){

        try{

            //创建模板加载配置器
            Configuration configurationObj = new Configuration(Configuration.getVersion());

            //Freemarker的模板加载器
            StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
            stringTemplateLoader.putTemplate("template",template );

            //配置模板加载器
            configurationObj.setTemplateLoader(stringTemplateLoader);


            //获取模板
            Template templateObj = configurationObj.getTemplate("template");
            String html = FreeMarkerTemplateUtils.processTemplateIntoString(templateObj, model);
            return html;


        }catch (Exception e){

        e.printStackTrace();

        }
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值