使用Freemarker来页面静态化,与Spring整合使用

页面静态化介绍

页面静态化其实就是将原来的动态网页(例如通过ajax请求动态获取数据库中的数据并展示的网页)改为
通过静态化技术生成的静态网页,这样用户在访问网页时,服务器直接给用户响应静态html页面,没有
了动态查询数据库的过程。

那么这些静态HTML页面还需要我们自己去编写吗?其实并不需要,我们可以通过专门的页面静态化技
术帮我们生成所需的静态HTML页面,例如:Freemarker、thymeleaf等。

FreeMarker

freemarker中文官方文档

什么是FreeMarker?

在这里插入图片描述

实际上用程序语言编写的程序就是模板。 FTL (代表FreeMarker模板语言)。 这是为编写模板设计的非常简单的编程语言。

模板(FTL编程)是由如下部分混合而成的:

文本:文本会照着原样来输出。

插值:这部分的输出会被计算的值来替换。插值由 ${ and } 所分隔(或者 #{ and },这种风格已经不建议再使用了;点击查看更多)。

FTL 标签:FTL标签和HTML标签很相似,但是它们却是给FreeMarker的指示, 而且不会打印在输出内容中。

注释:注释和HTML的注释也很相似,但它们是由 <#-- 和 -->来分隔的。注释会被FreeMarker直接忽略, 更不会在输出内容中显示。

我们来看一个具体的模板。其中的内容已经用颜色来标记了: 文本, 插值, FTL 标签, 注释。为了看到可见的 换行符, 这里使用了
在这里插入图片描述
在这里插入图片描述
请注意非常重要的一点: 插值 仅仅可以在 文本 中使用。 (也可以是字符串表达式;请参考 后续内容)

FTL 标签 不可以在其他 FTL 标签 和 插值中使用。比如, 这样做是 错误 的: <#if <#include ‘foo’>=‘bar’>…</#if>

Freemarker的指令(在下面的案列中解释)

简单使用Freemarker来生成静态化页面

搭建maven工程

在这里插入图片描述

pom.xml

需要引入freemarker的依耐

<?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.fs</groupId>
    <artifactId>FreemarkerDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
    </dependencies>
</project>
创建模板文件

模板文件中有四种元素:
1、文本,直接输出的部分 2、注释,即<#–…-->格式不会输出 3、插值(Interpolation):即${…}部分,
将使用数据模型中的部分替代输出 4、FTL指令:FreeMarker指令,和HTML标记类似,名字前加#予以
区分,不会输出
Freemarker的模板文件后缀可以任意,一般建议为ftl。

test.ftl
<html>
<head>
    <meta charset="utf-8">
    <title>Freemarker入门</title>
</head>
<body>
<#--我只是一个注释,我不会有任何输出  -->
${name}你好,${message}
<hr>
<#--assign指令用于在页面上定义一个变量 -->
<#--(1)定义简单类型	assign指令用于在页面上定义一个变量  定义变量方便测试生产的模板内容-->
<#assign linkman="付先生">
联系人:${linkman}
<#--(2)定义对象类型	-->
<#assign info={"mobile":"13812345678",'address':'重庆'} >
电话:${info.mobile} 地址:${info.address}
<hr>
<#--include指令用于模板文件的嵌套 引入模板文件 模板文件的目录会在java代码中指定
configuration.setDirectoryForTemplateLoading(new File(文件路径)); -->
<#include "head.ftl"/>

<hr>
<#--if指令用于判断-->
<#--(1)在模板文件中使用if指令进行判断  (2)在java代码中为success变量赋值-->
<#if success=true>
    你已通过实名认证
<#else>
    你未通过实名认证
</#if>
<hr>
<#--list指令用于遍历 (1)在模板文件中使用list指令进行遍历  (2)在java代码中为goodsList赋值-->
<#list goodsList as goods>
商品名称: ${goods.name} 价格:${goods.price}<br>
</#list>

</body>
</html>
head.ftl
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>头部</title>
</head>
<body>
<h1>---------------头部信息---------------</h1>
</body>
</html>
生成静态文件的java代码

使用步骤:
第一步:创建一个 Configuration 对象,直接 new 一个对象。构造方法的参数就是 freemarker的版本
号。
第二步:设置模板文件所在的路径。
第三步:设置模板文件使用的字符集。一般就是 utf-8。
第四步:加载一个模板,创建一个模板对象。
第五步:创建一个模板使用的数据集,可以是 pojo 也可以是 map。一般是 Map。
第六步:创建一个 Writer 对象,一般创建 FileWriter 对象,指定生成的文件名。
第七步:调用模板对象的 process 方法输出文件。
第八步:关闭流。

package com.fs.testfreemarker;

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

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestFreemarker {
    public static void main(String[] args) throws Exception {
        //1.创建配置类
        Configuration configuration = new Configuration(Configuration.getVersion());
        //2.设置模板所在的目录
        configuration.setDirectoryForTemplateLoading(new File("E:\\IdeaProjects\\Demo01\\test\\FreemarkerDemo\\src\\main\\resources\\template"));
        //3.设置字符集
        configuration.setDefaultEncoding("utf-8");

        //4.加载模板
//        Template template = configuration.getTemplate("test.ftl");
        Template template = configuration.getTemplate("test.ftl","utf-8");
        //5.创建数据模型,我们模板中有 ${name}你好,${message} 所以我们通过map来设置数据
        Map map = new HashMap();
        map.put("name", "小付");
        map.put("message", "欢迎使用freemarker!");

        //为if指令赋值
        map.put("success", true);

        //为list指令赋值
        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);

        //6.创建Writer对象
        FileOutputStream  file= new FileOutputStream("E:\\IdeaProjects\\Demo01\\test\\FreemarkerDemo\\src\\main\\resources\\out\\testFreemarker.html");
        //utf-8字符集输出
        OutputStreamWriter out = new OutputStreamWriter(file, "utf-8");

        //7.输出
        template.process(map, out);
        //8.关闭Writer对象
        out.close();

    }
}

运行后生成的html静态页面testFreemarker.html
<html>
<head>
    <meta charset="utf-8">
    <title>Freemarker入门</title>
</head>
<body>
小付你好,欢迎使用freemarker!
<hr>
联系人:付先生
电话:13812345678 地址:重庆
<hr>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>头部</title>
</head>
<body>
<h1>---------------头部信息---------------</h1>
</body>
</html>
<hr>
    你已通过实名认证
<hr>
商品名称: 苹果 价格:5.8<br>
商品名称: 香蕉 价格:2.5<br>
商品名称: 橘子 价格:3.2<br>

</body>
</html>
浏览器打开

在这里插入图片描述

freemarker与Spring整合

applicationContext.xml

在application.xml中使用Bean标签将org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer交给spring的IOC管理

就可以使用FreeMarkerConfigurer得到Configuration 进行静态页面生成

    //注入freemarker
    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    //通过FreeMarkerConfigurer获得freemarker的配置类
    Configuration configuration = freeMarkerConfigurer.getConfiguration();

    <!--    配置freemarker-->
    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <!--        指定模板文件的位子-->
        <property name="templateLoaderPath" value="/WEB-INF/ftl"/>
        <!--        指定字符集-->
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>
 <!--    引入动态生成的静态页面地址,在java中使用@Value注入-->
    <context:property-placeholder location="classpath:freemarker.properties"/>

freemarker.properties

# freemarker动态生成的静态页面输出的地址,实际生产部署是生产在tomcat的中,
outPut.Path=E:/IdeaProjects/projectOne/fs-health-parent/health_mobile/src/main/webapp/pages

java(下面的代码为伪代码.理解思想)


public class Test {

    //注入freemarker
    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    //从properties文件中注入freemarker生成的静态页面地址
    @Value("${outPut.Path}")
    private String outPutPath;


        /*
        由于我们现在health_mobile用户微信使用的页面的数据是异步请求获得的,用户每次使用套餐预约的时候,setmeal.html,setmeal_detail.html
        中的套餐数据,检查组,检查项,都是每次查询数据库得到的,这样加载页面十分缓慢,效率太低,用户体验度极差等

        解决上述方法,我们使用页面静态化技术,让我们用户每次访问的页面数据事写死的,静态的,每次用户访问,直接传递页面到用户端解析,不在请求
        数据库查询,这个静态化页面中的数据如何填充?

        我们查询的数据只要不进行修改,页面数据是不会变的,所以,我们后台只要添加了套餐信息,或者修改了套餐信息
        就使用freemarker,先创建一个模板页面,页面中的数据使用 assign指令  include指令  if指令  list指令等指令(查看WEB-INF中的文件)
        填充原来数据应该显示的位子,然后我们使用java代码动态的去指令的位子替换数据,然后生成一个静态页面,这样,用户访问的时候加载静态页面
        就不每次访问去数据库查询数据,大大提高了效率
         */
        //每当用户点击添加套餐的时候,执行生成静态页面方法
        generateMobileStaticHtml();
    


    /**
     * 生成移动静态Html
     * 下面的代码是伪代码,dao代表调用dao查询的数据
     */
    public void generateMobileStaticHtml(){
        //准备模板文件所需要的数据,先查询出所有的套餐信息,调用自己的查询所有方法
        List<Setmeal> setMealList = dao.findAll();
        //生成套餐列表静态页面mobile_setmeal.ftl,数据查询出来赋值给这个模板将这个模板变成静态页面
        HashMap<String, Object> objectHashMap = new HashMap<>();
        //将查询出的值放在map中
        objectHashMap.put("setmealList",setMealList);
        //调用生成静态页面,生成套餐列表静态页面
        generateHtml("mobile_setmeal.ftl","m_setmeal.html",objectHashMap);

        //生成套餐详情静态页面mobile_setmeal_detail.ftl数据查询出来赋值给这个模板,变成静态页面
        //由于点击套餐详情页面是多个的,查询出的每个详情页面就生成一个动态页面,页面的名字由套餐的id结尾

        //先遍历集合,得到每个套餐的id,在查询出每个套餐信息的详细数据,然后使用模板生成静态页面
        for (Setmeal setmeal : setMealList) {
            //每次遍历就封装一个map
            HashMap<String, Object> stringObjectHashMap = new HashMap<>();
            //封装查询套餐信息的详细信息,封装到map中,让freemarker来解析出静态页面
            stringObjectHashMap.put("setmeal",this.findSetMealDetails(setmeal.getId()));
            //然后调用方法生成静态页面.名字结尾拼接上id
            this.generateHtml("mobile_setmeal_detail.ftl","setmeal_detail_"+setmeal.getId()+".html",stringObjectHashMap);
        }
    }

    /**
     * 用于生成静态页面Dao指定的目录
     * @param templateName 传递的模板名称
     * @param htmlName 生成的模板名称
     * @param objectHashMap 查询出的值,赋值给模板的指令符
     */
    public void generateHtml(String templateName, String htmlName, Map<String, Object> objectHashMap){
        //通过FreeMarkerConfigurer获得freemarker的配置类
        Configuration configuration = freeMarkerConfigurer.getConfiguration();
        //由于我们spring配置文件中添加freeMarkerConfigurer这个bean的时候指定了模板文件的地址,所以我们这里只需要传递模板文件的名就可以
        Writer out = null;
        try {
            //给定模板文件,得到模板对象
            Template template = configuration.getTemplate(templateName);
            //指定模板对象生成的文件地址(在properties文件中指定了的)以及文件名称
            File file = new File(outPutPath + "\\" + htmlName);
            //创建字符缓冲流
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
            //给模板文件写入数据,并传入一个字符输出流,
            template.process(objectHashMap,out);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //判断字符缓存流是否为null
            if (out != null){
                try {
                    //不为null.说明有数据,那就刷新流,写到磁盘中
                    out.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值