【Spring Boot】视图渲染技术之Freemarker

一、引言

1、什么是Freemarker

        FreeMarker是一款模板引擎,基于模板和要改变的数据,并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

        FreeMarker是免费的,基于Apache许可证2.0版本发布。其模板编写为FreeMarker Template Language(FTL),属于简单、专用的语言。它帮助从开发人员(Java 程序员)中分离出网页设计师(HTML设计师)。

        模板编写为FreeMarker Template Language (FTL)。它是简单的,专用的语言, 不是 像PHP那样成熟的编程语言。 那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。

2、Freemarker模板组成部分

FreeMarker模板文件主要由如下4个部分组成:

  1. 文本:直接输出的部分

  2. 注释:使用<#-- ... -->格式做注释,里面内容不会输出

  3. 插值:即${...}或#{...}格式的部分,类似于占位符,将使用数据模型中的部分替代输出

  4. FTL指令:即FreeMarker指令,全称是:FreeMarker Template Language,和HTML标记类似,但名字前加#予以区分,不会输出

3、FreeMarker与Web容器无关

        FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP,故此FreeMarker不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java等各种文本文件。

        在Java Web领域,FreeMarker是应用广泛的模板引擎,主要用于MVC中的view层,生成html展示数据给客户端,可以完全替代JSP。

        FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写,模板中没有业务逻辑,外部Java程序通过数据库操作等生成数据传入模板(template)中,然后输出页面。它能够生成各种文本:HTML、XML、RTF、Java源代码等等,而且不需要Servlet环境,并且可以从任何源载入模板,如本地文件、数据库等等。

4、优缺点

①优点

FreeMarker的诞生是为了取代JSP。虽然JSP功能强大,可以写Java代码实现复杂的逻辑处理,但是页面会有大量业务逻辑,不利于维护和阅读,更不利于前后台分工,容易破坏MVC结构,所以舍弃JSP,选择使用FreeMarker是大势所趋。当前很多企业使用FreeMarker取代JSP,FreeMarker有众多的优点,如下所示:

  • 很好地分离表现层和业务逻辑

JSP功能很强大,它可以在前台编写业务逻辑代码,但这也带来了一个很大的弊端——页面内容杂乱,可读性差,这将会大大增加后期的维护难度。而FreeMarker职责明确,功能专注,仅仅负责页面的展示,从而去掉了繁琐的逻辑代码。FreeMarker的原理就是:模板+数据模型=输出,模板只负责数据在页面中的表现,不涉及任何的逻辑代码,而所有的逻辑都是由数据模型来处理的。用户最终看到的输出是模板和数据模型合并后创建的。

  • 提高开发效率

众所周知,JSP在第一次执行的时候需要转换成Servlet类,之后的每次修改都要编译和转换。这样就造成了每次修改都需要等待编译的时间,效率低下。而FreeMarker模板技术并不存在编译和转换的问题,所以就不会存在上述问题。相比而言,使用FreeMarker可以提高一定的开发效率。

  • 明确分工

JSP页面前后端的代码写到了一起,耦合度很高,前端开发需要熟悉后台环境,需要去调试,而后台开发人员需要去做不熟悉的前端界面设计。对两者而言,交替性的工作需要花费一定的学习成本,效率低下。而使用FreeMarker后,前后端完全分离,大家各干各的,互不影响。

  • 简单易用,功能强大

FreeMarker支持JSP标签,宏定义比JSP Tag方便,同时内置了大量常用功能,比如html过滤,日期金额格式化等等。FreeMarker代码十分简洁,上手快,使用非常方便。

综合以上得到以下:

  1. 彻底的分离表现层和业务逻辑,使得页面内容更加清晰,后期修改和维护更加方便。
  2. 提高开发效率,因为FreeMarker模板技术不存在编译和转换的问题。
  3. 使得开发过程中的人员分工更加明确,程序员和界面设计人员可以更好地协作。

③缺点

  1. 无法在模板中使用Java代码,这可能会限制一些复杂逻辑的实现。
  2. 相对于JSP来说,FreeMarker的模板语法较为简单,可能无法满足一些复杂的页面需求。

二、Freemarker常见指令

1、处理不存在的值

  • 不存在值检测操作符

使用形式: unsafe_expr??(unsafe_expr)??

这个操作符告诉我们一个值是否存在。基于这种情况, 结果是 truefalse

<#if name??>
  存在
<#else>
  不存在
</#if>
  • exists用在逻辑判断

exists用作逻辑判断,返回的是true或者false。

<#if name?exists>
    ${name}
</#if>
  • if_exists用来打印东西

if_exists用于输出的时候,如果存在则输出,不存在就输出空字符串

${name?if_exists}

2、assign

使用该指令你可以创建一个新的变量, 或者替换一个已经存在的变量。语法格式如下:

<#assign name1=value1 name2=value2 ... nameN=valueN>
或
<#assign name>
  hello
</#assign>

案例演示:

<#-- 创建一个str的变量 -->
<#assign str="hello">
<#-- 输出str -->
${str} <br>
<#-- 一次创建多个变量 -->
<#assign num=1 names=["zs","ls","ww"] >
${num} -- ${names?join(",")}

3、if/elseif/else

你可以使用 ifelseifelse 指令来条件判断是否越过模板的一个部分。 *condition* 必须计算成布尔值, 否则错误将会中止模板处理。elseifelse 必须出现在 if 内部 (也就是,在 if 的开始标签和结束标签之间)。 if 中可以包含任意数量的 elseif(包括0个) 而且结束时 else 是可选的。

<#if 条件1>
  ...
<#elseif 条件2>
  ...
<#elseif 条件3>
  ...
...
<#else>
  ...
</#if>

4、list

list 指令执行在 list 开始标签和 list 结束标签 ( list 中间的部分) 之间的代码, 对于在序列(或集合)中每个值指定为它的第一个参数。 对于每次迭代,循环变量将会存储当前项的值。

循环变量仅仅存在于 list 标签体内。 而且从循环中调用的宏/函数不会看到它(就像它只是局部变量一样)。

<#list s as item>
    ${s.name}
<#else>
    暂无
</#list>

list 中的 else 仅从 FreeMarker 2.3.23 版本开始支持。

注意:

  • else 部分是可选的, 而且仅仅从 FreeMarker 2.3.23 版本开始支持。

  • sequence: 将我们想要迭代的项,算作是序列或集合的表达式

  • item: 循环变量的名称 (不是表达式)

<#list arrs as item>
    ${item}
<#else>
    集合是空的
</#list>

5、include

可以使用它在你的模板中插入另外一个 FreeMarker 模板文件 (由 path 参数指定)

<#include path>
或
<#include path options>

这里:

  • path: 要包含文件的路径;

  • options: 一个或多个这样的选项: encoding=encoding, parse=parse

    • encoding: 算作是字符串的表达式

    • parse: 算作是布尔值的表达式(为了向下兼容,也接受一部分字符串值)

    • ignore_missing: 算作是布尔值的表达式

<h1>Hello Freemarker</h1>
<#include "/common/head.ftl">

三、SpringBoot整合Freemarker

1、配置

引入依赖pom.xml

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

添加application.ymlapplication.properties文件配置

spring:
  #  freemarker
  freemarker:
    # 设置模板后缀名
    suffix: .ftl
    # 设置文档类型
    content-type: text/html
    # 设置页面编码格式
    charset: UTF-8
    # 设置页面缓存
    cache: false
    # 设置ftl文件路径
    template-loader-path: classpath:/templates
    # 设置静态文件路径,js,css等
    mvc:
      static-path-pattern: /static/**

2、新建模板

这里Freemarker选项需要到settings(设置) -> Editor(编辑器) -> File And Code Templates(文件和代码模板)中进行配置。扩展最好还是用ftl

最后,请选择resources/templates目录,右键 New -> Freemarker 新建模板文件(.ftl)。

创建FreemarkerController,并配置跳转页面路径:

@Controller
public class FreemarkerController {

    @RequestMapping("/")
    public String index() {
        return "index";
    }
}

四、综合案例

新建一个common.ftl文件引入我们的资源.比如我们的jQuery的资源

<#assign ctx="${springMacroRequestContext.contextPath}">
<link rel="stylesheet" href="${ctx}/bootstrap-3.4.1-dist/css/bootstrap.css">
<script src="${ctx}/jquery-3.6.1.js"></script>
<script src="${ctx}/bootstrap-3.4.1-dist/js/bootstrap.js"></script>

index.ftl里面进行页面的编写。

<!doctype html>
<html lang="zh">
<head>
    <title>index</title>
    <style>
        td {
            padding: 20px;
            text-align: center;
        }
    </style>
    <#include "common.ftl">
</head>
<body>
<a href="${ctx}/save">增加</a>
<#if Books??>
    <table class="table table-striped">
        <#list Books as book>
            <tr>
                <td>${book.id}</td>
                <td>${book.bookname}</td>
                <td>${book.price}</td>
                <td>${book.booktype}</td>
                <td>
                    <a href="${ctx}/del?id=${book.id}">删除</a>
                    <a href="${ctx}/saveEdit?id=${book.id}">修改</a>
                </td>
            </tr>
        </#list>
    </table>
</#if>
</body>
</html>

在这之前我们调用好我们的方法并且能实现,最好我们调用Controller层。

import com.example.springboot01.entity.TBook;
import com.example.springboot01.service.TBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

import java.util.List;

@Controller
public class FreemarkerController {
    @Autowired
    private TBookService tBookService;

    @RequestMapping("/")
    public String index(Model model) {
        List<TBook> tBooks = tBookService.selectAll();
        model.addAttribute("Books", tBooks);
        return "index";
    }

运行我们的spring boot访问看结果。

save.ftl文件代码

<#--初始化-->
<#--${book = null}-->
<#--${edit = false}-->

<#--检查是否选择/存在了-->
<#--<#if book??>-->
<#--    ${edit = true}-->
<#--    ${book = books[bookId]}-->
<#--</#if>-->

<html>
<head>
    <title>Books</title>
</head>
<body>
<#--<h1>Books</h1>-->
<#if book??>
    <h1>修改</h1>
    <form method="post" action="/update">
        <input type="hidden" name="id" value="${book.id}">
        <div class="form-group">
            <label for="bookname">书名:</label>
            <input type="text" class="form-control" id="bookname" name="bookname" value="${book.bookname}"
                   placeholder="请输入书籍名称">
        </div>
        <div class="form-group">
            <label for="price">价格:</label>
            <input type="number" class="form-control" id="price" name="price" value="${book.price}"
                   placeholder="请输入书籍价格">
        </div>
        <div class="form-group">
            <label for="booktype">书籍类型:</label>
            <select class="form-control" id="booktype" name="booktype">
                <option>历史</option>
                <option>言情</option>
                <option>悬疑</option>
                <option>恐怖</option>
                <option>科幻</option>
                <option>诡异</option>
                <option>玄幻</option>
                <option>爱情</option>
                <option>冒险</option>
                <option>热血</option>
            </select>
        </div>

        <button type="submit" class="btn btn-primary">提交</button>
    </form>

<#else>
    <h1>增加</h1>
    <form method="post" action="/add">
        <div class="form-group">
            <label for="bookname">书名:</label>
            <input type="text" class="form-control" id="bookname" name="bookname" value="" placeholder="请输入书籍名称">
        </div>
        <div class="form-group">
            <label for="price">价格:</label>
            <input type="number" class="form-control" id="price" name="price" value="" placeholder="请输入书籍价格">
        </div>
        <div class="form-group">
            <label for="booktype">书籍类型:</label>
            <select class="form-control" id="booktype" name="booktype">
                <option>历史</option>
                <option>言情</option>
                <option>悬疑</option>
                <option>恐怖</option>
                <option>科幻</option>
                <option>诡异</option>
                <option>玄幻</option>
                <option>爱情</option>
                <option>冒险</option>
                <option>热血</option>
            </select>
        </div>

        <button type="submit" class="btn btn-primary">提交</button>
    </form>

</#if>
</body>
</html>

分享就到这里感谢观看,欢迎大家在评论区讨论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/247389.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LAMP平台部署及应用

1、安装PHP软件包 1.1、准备工作 检查软件是否安装&#xff0c;避免冲突 [rootyang ~]# rpm -e php php-cli php-ldap php-common php-mysql --nodeps 错误&#xff1a;未安装软件包 php 错误&#xff1a;未安装软件包 php-cli 错误&#xff1a;未安装软件包 php-ldap 错误…

使用 Python 使用贝叶斯神经网络从理论到实践

一、说明 在本文中&#xff0c;我们了解了如何构建一个机器学习模型&#xff0c;该模型结合了神经网络的强大功能&#xff0c;并且仍然保持概率方法进行预测。为了做到这一点&#xff0c;我们可以构建所谓的贝叶斯神经网络。 这个想法不是优化神经网络的损失&#xff0…

2. PyTorch——Tensor和Numpy

2.1Tensor和Numpy Tensor和Numpy数组之间具有很高的相似性&#xff0c;彼此之间的互操作也非常简单高效。需要注意的是&#xff0c;Numpy和Tensor共享内存。由于Numpy历史悠久&#xff0c;支持丰富的操作&#xff0c;所以当遇到Tensor不支持的操作时&#xff0c;可先转成Numpy…

获取和移除cookie的方法

下载npm的cookie插件, 在utils.js文件中引入插件: 封装原始的Cookies.get()方法: 在xxxx.vue文件中引入方法: 使用getCookie方法获取cookie: 封装 移除cookie: export const removeCookie name>{ const options { path: /, domain: xxx.com }; Cookies.remove(name, opti…

18 5G - NR物理层解决方案支持6G非地面网络中的高移动性

文章目录 非地面网络场景链路仿真参数实验仿真结果 非地面网络场景 链路仿真参数 实验仿真结果 Figure 5 && Figure 6&#xff1a;不同信噪比下的BER和吞吐量 变量 SISO 2x2MIMO 2x4MIMO 2x8MIMOReyleigh衰落、Rician衰落、多径TDL-A(NLOS) 、TDL-E(LOS)(a)QPSK (b)16…

玩期货,千万要注意不同软件的设置啊

参加某公司的期货交易模拟选拔&#xff0c;用的是博易大师&#xff0c;结果这个软件的止损线巨坑&#xff0c;当天下午设置的止损线&#xff0c;在收盘之后软件关闭的情况下就自动作废了&#xff0c;到了晚上夜盘如果价格超相反方向走了&#xff0c;那可能导致巨亏。 幸亏是模拟…

nginx的location与rewrite

目录 一.location 二.rewrite rewrite跳转实现&#xff1a; 语法格式&#xff1a;rewrite [flag]; flag标记说明&#xff1a; 三.基于域名跳转 四.基于ip跳转 五.基于旧域名跳转到新域名后面加目录 六.基于参数匹配的跳转 可以同过全局变量来匹配&#xff1a; 基于目…

最高级别认可!喂车科技荣获国际CMMI5级认证

近日&#xff0c;喂车科技顺利通过全球软件领域最高级别认证CMMI 5级&#xff08;简称CMMI5&#xff09;认证&#xff01; 此次荣获CMMI5级认证&#xff0c;意味着喂车科技在研发管理体系、项目实施交付服务以及项目管理水平等方面均已达到国际领先水平&#xff0c;能够为客户…

如何远程访问Axure RP制作的本地web站点实现协同办公

文章目录 前言1.在AxureRP中生成HTML文件2.配置IIS服务3.添加防火墙安全策略4.使用cpolar内网穿透实现公网访问4.1 登录cpolar web ui管理界面4.2 启动website隧道4.3 获取公网URL地址4.4. 公网远程访问内网web站点4.5 配置固定二级子域名公网访问内网web站点4.5.1创建一条固定…

在windows系统搭建LVGL模拟器(codeblock工程)

1.codeblock准备 下载codeblock(mingw)&#xff0c;安装。可参考网上教程。 2.pc_simulator_win_codeblocks 工程获取 仓库地址&#xff1a;lvgl/lv_port_win_codeblocks: Windows PC simulator project for LVGL embedded GUI Library (github.com) 拉取代码到本地硬盘&…

机器学习算法应用场景与评价指标

机器学习算法&#xff08;一&#xff09;——分类 机器学习算法&#xff08;二&#xff09;——回归 机器学习算法&#xff08;三&#xff09;——异常检测 一、应用场景 机器学习的算法选择大部分依赖于具体的问题类型和数据特征。下面是一些典型的场景以及对应的常用算法&am…

面对知识经济的发展,企业该如何做好知识管理?

面对知识经济的发展&#xff0c;企业犹如逆水行舟&#xff0c;不进则退&#xff0c;而知识管理已经成为了企业赖以生存和发展的关键。大家可能对知识经济这个词比较陌生&#xff0c;简单来说&#xff0c;知识经济就是指在经济活动中&#xff0c;知识的产生、获取、传播和应用成…

点石成金》》》从“沙粒”蜕变到“芯片”

每个半导体产品的制造都需要数百个工艺&#xff0c;Lam Research将整个制造过程分为八个步骤&#xff1a;晶圆加工-氧化-光刻-刻蚀-薄膜沉积-互连-测试-封装。 01 晶圆加工 所有半导体工艺都始于一粒沙子&#xff01;因为沙子所含的硅是生产晶圆所需要的原材料。晶圆是…

C++ Qt开发:DateTime日期时间组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍QDateTime日期与时间组件的常用方法及灵活运用…

【评测脚本】agent资源监控

背景 在之前的文章中提到过,我们在测试过程中需要对机器的资源进行评测。在实际工作中,我们还会经常遇到的场景就是对于agent-server类型的业务,当部署完成后,需要对部署在机器上的agent进行资源占用的观测,不能舍本逐末,由于agent的异常资源占用,导致原有业务受机器资…

直播美颜SDK开发实战:从入门到精通

直播美颜SDK的应用已经成为许多直播平台和开发者关注的焦点。本文将带领读者深入探讨直播美颜SDK的开发实战&#xff0c;从入门到精通的过程。 1.引言 直播美颜SDK是一种集成了图像处理、人脸识别、滤镜算法等技术的开发工具包。通过使用该SDK&#xff0c;开发者能够为直播应…

酸奶店怎么做营销活动来引流,才能吸引顾客进店

今天我想和大家分享的是酸奶店怎么做营销活动来引流&#xff0c;才能吸引顾客进店。 本人经营酸奶店5年时间&#xff0c;以下活动方式都是我亲身经历过的&#xff0c;希望能给大家一些参考。 随着人们对健康饮食的追求不断提高&#xff0c;酸奶作为一种营养丰富、口感独特的食…

IDEA调整内存大小

一、IDEA开启内存显示 双击shift,搜索show memory indicator 打开后重启&#xff0c;右下角显示IDEA内存占用情况 开启后右下角会显示 二、调整内存 双击shift,搜索vmoption 修改-Xms和-Xmx参数&#xff0c;如下&#xff1a; -Xms:最小内存 -Xmx:最大内存 设置完成后&…

apt-mark工具介绍(标记或取消标记软件包,防止特定软件包被自动更新或删除)

文章目录 apt-mark工具深度解析1. apt-mark概述1.1 apt-mark定义1.2 apt-mark作用 2. apt-mark常用命令2.1 标记软件包为手动安装2.2 标记软件包为自动安装2.3 阻止软件包更新2.4 允许软件包更新 3. 疑难技术点解析3.1 如何查看软件包的标记状态3.2 如何解决软件包依赖性问题 4…

Python | 高斯分布拟合示例

什么是正态分布或高斯分布&#xff1f; 当我们绘制一个数据集&#xff08;如直方图&#xff09;时&#xff0c;图表的形状就是我们所说的分布。最常见的连续值形状是钟形曲线&#xff0c;也称为高斯分布或正态分布。 它以德国数学家卡尔弗里德里希高斯的名字命名。遵循高斯分布…