freemarker

Freemarker介绍

freemarker是一个模板引擎: 是基于模板和要改变的数据,合并生成输出文本(HTML网页,电子邮件,配置文件,源代码)。是一个Java类库

上边显示,在后端将数据查出来,会将数据封装起来,称之为数据模型model     将一个前端的模板使用freemarker进行结合,就会生成一个页面。

数据模型+模板=输出  例子

数据模型

模板

输出

freemarker使用步骤

1:添加依赖


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

2 添加配置到配置文件

spring:
  freemarker:
    cache: false  #关闭模板缓存,方便测试
    settings:
      template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试
    suffix: .ftl               #指定Freemarker模板文件的后缀名

 freemarker使用demo

1 创建模板

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
</head>
<body>
<b>普通文本 String 展示:</b><br><br>
Hello <br>
<hr>
<b>对象Student中的数据展示:</b><br/>
姓名:${stu.name}<br/>
年龄:${stu.age}
<hr>
</body>
</html>

 2 创建数据模型

@Controller
public class Test01Basic {


    @GetMapping("/test01-basic")
    public String test01Basic(Model model) {
        Student student = new Student();
        student.setAge(18);
        student.setMoney(20F);
        student.setName("衡老师");
        model.addAttribute("stu", student);
//这里返回的必须是模板的文件名称
        return "01-basic";
    }
}

合并的页面:

 解释: 模型返回一个 01-basic   意思就是上边的模板名称。

在模型数据中将student对象添加到model中,key为stu       所以在上边的模板中就会stu.name   意思就是调用key为stu的值,将student对象调用出来然后再得到名称和年龄

注意:这里如果使用@RestController那么就会将返回的数据变为json,这不是想要的数据,所以要使用controller或者ViewAndModel

freemarker的基础使用

1 插值

格式:  ${....}

模板

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
</head>
<body>
<b>普通文本 String 展示:</b><br><br>
Hello <br>
<hr>
<b>对象Student中的数据展示:</b><br/>
姓名:${stu.name}<br/>
年龄:${stu.age}
<hr>
</body>
</html>

数据模型

@Controller
public class Test01Basic {


    @GetMapping("/test01-basic")
    public String test01Basic(Model model) {
        Student student = new Student();
        student.setAge(18);
        student.setMoney(20F);
        student.setName("衡老师");
        model.addAttribute("stu", student);
        //这里返回的必须是模板的文件名称
        return "01-basic";
    }
}

 2 集合   list    map

模板

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

<#-- list 数据的展示 -->
<b>展示list中的stu数据:</b>
<br>
<br>
<table>
    <tr>
        <td>序号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>钱包</td>
        <td>集合长度:${list?size}</td>
    </tr>
    <#--遍历集合list,将里面的值遍历取出来-->
    <#list list as stu>
        <#if stu.name=='刘墩墩'>
            <tr style="color: aquamarine">
                <td>${stu_index+1}</td>
                <td>${stu.name}</td>
                <td>${stu.age}</td>
                <td>${stu.money!""}</td>
            </tr>
        <#else >
            <tr>
                <td>${stu_index+1}</td>
                <td>${stu.name}</td>
                <td>${stu.age}</td>
                <td>${stu.money!""}</td>
            </tr>
        </#if>
    </#list>
</table>
<hr>


<#-- Map 数据的展示 -->
<b>map数据的展示:</b>
<br/><br/>
<a href="###">方式一:通过map['keyname'].property</a><br/>
输出stu1的学生信息:<br/>
姓名:${map['tudent1'].name}<br/>
年龄:${map['tudent1'].age}
<br/>
<a href="###">方式二:通过map.keyname.property</a><br/>
输出stu2的学生信息:<br/>
姓名:${map.tudent2.name}<br/>
年龄:${map.tudent2.age}<br/>
<br/>
<a href="###">遍历map中两个学生信息:</a><br/>
<table>
    <tr>
        <td>序号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>钱包</td>
    </tr>
    <#list map?keys as key>
        <tr>
            <td>${key_index}</td>
            <td>${map[key].name}</td>
            <td>${map[key].age}</td>
            <#--非空判断    如果money没有非空判断,那么Java中没有给money赋值,就会报错,这时候需要加入非空判断   非空有两种:1  ..money??   2: ...money!""   -->
            <td>${map[key].money!""}</td>
        </tr>
    </#list>
</table>
<#--就是比如有很长的数就会三位数一个逗号:  123,456,789      加了c:123456789-->
<b>c函数:</b>
不加c函数:${point}<br>
添加c函数:${point?c}
<hr>

</body>
</html>

模型

@Controller
public class Test03ListAndMap {
    @GetMapping("/03-List-Map")
    public String test01Basic(Model model) {
        Student tudent1 = new Student();
        tudent1.setAge(18);
//        tudent1.setMoney(20F);
        tudent1.setName("衡老师");
        tudent1.setBirthday(new Date());
        model.addAttribute("stu", tudent1);

        Student tudent2 = new Student();
        tudent2.setAge(18);
//        tudent2.setMoney(20F);
        tudent2.setName("刘老师");
        tudent2.setBirthday(new Date());
        model.addAttribute("stu2", tudent2);

        Student tudent3 = new Student();
        tudent3.setAge(18);
//        tudent3.setMoney(20F);
        tudent3.setName("刘小平");
        tudent3.setBirthday(new Date());
        model.addAttribute("stu3", tudent3);

        Student tudent4 = new Student();
        tudent4.setAge(18);
//        tudent4.setMoney(20F);
        tudent4.setName("刘墩墩");
        tudent4.setBirthday(new Date());
        model.addAttribute("stu4", tudent4);


        //将上边的对象存到list中,再将list存到model
        ArrayList<Student> list = new ArrayList<>();
        Collections.addAll(list, tudent1, tudent2, tudent3, tudent4);
        model.addAttribute("list", list);

        //将上边的对象存到map中,再将map存到model
        Map<String, Object> map = new HashMap<>();
        map.put("tudent2", tudent2);
        map.put("tudent3", tudent3);
        map.put("tudent4", tudent4);
        map.put("tudent1", tudent1);
        model.addAttribute("map", map);
        model.addAttribute("point", 123456789765L);
        return "03-List-Map";
    }
}

 结果

解释:  这里的map可以通过遍历key来完成.  集合中如果想要1,2,3有序显示可以使用${传过来的key_index}

3 if指令

<table>
    <tr>
        <td>姓名</td>
        <td>年龄</td>
        <td>钱包</td>
    </tr>
    <#list stus as stu >
        <#if stu.name='小红'>
            <tr style="color: red">
                <td>${stu_index}</td>
                <td>${stu.name}</td>
                <td>${stu.age}</td>
                <td>${stu.money}</td>
            </tr>
            <#else >
            <tr>
                <td>${stu_index}</td>
                <td>${stu.name}</td>
                <td>${stu.age}</td>
                <td>${stu.money}</td>
            </tr>
        </#if>
    </#list>
</table>

3 运算符

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
</head>
<body>
    <b>比较运算符</b>
    <br/>
    <br/>
    <dl>
        <dt> =/== 和 != 比较:</dt>
        <dd>
            <#if "xiaoming" == "xiaoming">
                字符串的比较 "xiaoming" == "xiaoming"
            </#if>
        </dd>
        <dd>
            <#if 10 != 100>
                数值的比较 10 != 100
            </#if>
        </dd>
    </dl>
    <dl>
        <dt>其他比较</dt>
        <dd>
            <#if 10 gt 5 >
                形式一:使用特殊字符比较数值 10 gt 5
            </#if>
        </dd>
        <dd>
            <#-- 日期的比较需要通过?date将属性转为data类型才能进行比较 -->
            <#if (date1?date >= date2?date)>
                形式二:使用括号形式比较时间 date1?date >= date2?date
            </#if>
        </dd>
    </dl>
    <br/>
<hr>
</body>
</html>

4 空值判断

控制使用   ??   代表是不是空

<#if stus??>
    <#list stus as stu>
    	......
    </#list>
    </#if>

5 如期格式化

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
</head>
<body>
<b>普通文本 String 展示:</b><br><br>
Hello <br>
<hr>
<b>对象Student中的数据展示:</b><br/>
姓名:${stu.name}<br/>
年龄:${stu.age}<br/>
价格:${stu.money}<br/>
<#--使用时间类型的参数,就要在前端指定需要使用的是什么类型的时间格式,date:年月日     time:时分秒    datetime:年月日时分秒   自定义时间格式:string("yyyy-MM-dd HH-mm-ss")-->
生日date:${stu.birthday?date}<br/>
生日time:${stu.birthday?time}<br/>
生日datetime:${stu.birthday?datetime}<br/>
生日string自定义时间:${stu.birthday?string("yyyy-MM-dd HH-mm-ss")}<br/>
<hr>
</body>
</html>

freemarker生成HTML文件示例

  @Test
    public void testHtml01() throws Exception {
        //1创建配置类信息
        Configuration configuration = new Configuration(Configuration.getVersion());
        //2对配置类进行配置
        String path = this.getClass().getResource("/templates/").getPath();
        configuration.setDirectoryForTemplateLoading(new File(path));
        configuration.setDefaultEncoding("utf-8");
        //获得模板文件对象
        Template template = configuration.getTemplate("01-basic.ftl");
        System.out.println("template = " + template);     //结果为01-basic.ftl为赋值时的内容
        //获得数据模型   就是将数据和模板进行结合
        String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, getTemplate());
        System.out.println("content = " + content);   //结果为template模板中的值和getTemplate()中的数据
        //转换为字节流
        InputStream inputStream = IOUtils.toInputStream(content);
        //将模板和数据结好的数据模型转换为字节流再通过IOUtils.copy(inputStream, outputStream);将字节流写道指定的文件
        FileOutputStream outputStream = new FileOutputStream(new File("G:\\Java就业班\\项目二\\每天资料\\day08资料\\index.html"));
        IOUtils.copy(inputStream, outputStream);
    }

将这个freemarker生成的HTML上传到七牛云中

//2 调用CoursePubService生成课程详情页并且上传到七牛云中
        //         调用之前需要先确保消息的幂等性,防止重复数据   course_pub表中的is_pub
        int count = this.count(
                Wrappers.lambdaQuery(CoursePub.class).eq(CoursePub::getId, coursePubMsg.getPubId()).eq(CoursePub::getIsPub, CoursePub.IS_PUB)
        );
        //调用之前需要先确保消息的幂等性,防止重复数据
        if (count > 0) {
            // 说明存在这个pubid的数据  直接结束,不能抛出异常因为这是已经发布的数据所以不需要操作,如果抛出异常那么就会导致从新发送
            log.info("课程已经发布,{}", coursePubMsg.getPubId());
            return;
        }
        CoursePub coursePub = getById(coursePubMsg.getPubId());
        Map<String, Object> modelMap = generateMap(coursePub);
        //生成课程详情页并且上传到七牛云中
        String HtmlString = null;
        try {
            Template template = configuration.getTemplate("learing_article.ftl");
            HtmlString = FreeMarkerTemplateUtils.processTemplateIntoString(template, modelMap);
        } catch (Exception e) {
            // e.printStackTrace();
            log.info("{},{}", CoursePublishErrorCode.E_120209.getDesc(), coursePubMsg.getPubId());
            return;
        }
        //上传到七牛云中
        //准备fileName
        String fileName = coursePub.getId() + ".html";
        //准备key    当kye中有例如  images/文件名     在七牛云中就是代表images文件夹中的文件
        String path = position+fileName;
        try {
            QiniuUtils.upload2Qiniu(accessKey, secretKey, bucket, HtmlString, path);
        } catch (Exception e) {
            //e.printStackTrace();
            log.info("上传HTML到七牛云失败,{}", coursePubMsg.getPubId());
            ExceptionCast.cast(CoursePublishErrorCode.E_120210);
        }
        // 3 将课程发布状态设置未0已经发布状态is_pub   这样是为了保证幂等性
        boolean updatePubStatus = update(
                Wrappers.lambdaUpdate(CoursePub.class)
                        .eq(CoursePub::getId, coursePub.getId())
                        .set(CoursePub::getChangeDate, LocalDateTime.now())
                        .set(CoursePub::getIsPub, CoursePub.IS_PUB)

        );
        //如果修改状态没有成功就记录下来,不能抛出异常是因为走到一步说明页面也上传成功了,如果抛出异常就会导致从新发送,数据重复上传
        if (!updatePubStatus) {
            log.info(CoursePublishErrorCode.E_120208.getDesc(), coursePub.getId());
        }

七牛云上传工具     Qiniu

 @Transactional
    public static boolean upload2Qiniu(String accessKey, String secretKey, String bucket, String contentText, String fileKey) {
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Zone.huadong());
        //上传管理对象
        UploadManager uploadManager = new UploadManager(cfg);

        try {
            byte[] uploadBytes = contentText.getBytes("utf-8");
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);
            try {
                Response response = uploadManager.put(uploadBytes, fileKey, upToken);

                //解析上传成功的结果
                if (response != null && response.isOK()) {
                    //解析上传成功的结果
                    DefaultPutRet putRet = new Gson().fromJson(response.bodyString(),
                                                               DefaultPutRet.class);
                    log.info("qiNiu result,  key:{}, hash:{}, response:{}",
                             putRet.key, putRet.hash, JSON.toJSONString(response));
                    return true;
                } else {
                    return false;
                }

            } catch (QiniuException ex) {
                Response r = ex.response;
                log.error("qiNiu error, response: {}", JSON.toJSONString(r));
            }
        } catch (UnsupportedEncodingException ex) {
            log.error("qiNiu error, response: {}", ex);
        }

        return false;

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值