FreeMarker

  

freemarker是一个用java开发的模版引擎,百度百科:

  

  

常用的java模版还有快要被抛弃的Jsp(熟悉)、Thymeleaf(了解)、Velocity(不知)

freemarker不关心数据的来源,知识根据模版的内容,将数据模型在模版中显示并输出文件;

快速入门难登大雅

SpringMVC在默认情况下是支持freemarker视图格式的,我们创建SpringBoot项目直接上Demo

pom.xml文件如下

  <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

日志安排:lomback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
<!--定义日志文件的存储地址,使用绝对路径-->
<property name="LOG_HOME" value="E:\logs"/>

<!-- Console 输出设置 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>utf8</charset>
</encoder>
</appender>

<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<fileNamePattern>${LOG_HOME}/xc.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- 异步输出 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="FILE"/>
</appender>

<logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="org.springframework.boot" level="DEBUG"/>
<root level="info">
<!--<appender-ref ref="ASYNC"/>-->
<appender-ref ref="FILE"/>
<appender-ref ref="CONSOLE"/>
</root>
</configuration>

配置文件:application.yml

server:
port: 8888
spring:
application:
name: test-freemarker
freemarker:
cache: false #关闭模版缓存
settings:
template_update_delay: 0 #检查模版更新延迟时间,0表示立即检查,如果大于0会有延迟,不利于测试唷
logging.level.org.springframework.boot.autoconfigure: ERROR #后来加上的,专治SpringBoot项目起来很多日志的情况

我们创建一个模型类,用于测试:待用

@Data
@ToString
public class People {
private String username;
private int age;
private Float money;
private List<People> friends; //他的朋友们
private People bestPeople; //他最好的朋友
}

创建模版:

在resource目录下创建templates目录,用来存放freemarker的模版,默认该目录

在templates中创建 test1.ftl内容如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>FreemarkerTest1</title>
</head>
<body>
欢迎您:${name} !
</body>
</html>

编写Controller:

@Controller
@RequestMapping("/freemarker")
public class FreemarkerController { //待用
@Autowired
private RestTemplate restTemplate; @RequestMapping("/test")
public String freemarker(Map<String,Object> map){
map.put("name", "警察叔叔");
return "test1";
}
}

编写启动类:

@SpringBootApplication
public class FreemarkerApplication {
public static void main(String[] args) {
SpringApplication.run(FreemarkerApplication.class);
} //待用
@Bean
public RestTemplate instance(){
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
}

等项目起来了,我们可以访问测试:http://localhost:8888/freemarker/test

  

有没有一种Jsp的味道在里面?反正我感觉是查询的意思,后面的语法有些改变

Freemarker基础

核心指令 —> 数据模型

Freemarker静态化依赖与数据模型和模版,下面定义数据模型

在上面的那个小Demo中,我们的数据模型也有使用,至于形参Map即为Freemarker静态化所需要的数据模型,在Map中填充数据即可

@Controller
@RequestMapping("/freemarker")
public class FreemarkerController { @Autowired
private RestTemplate restTemplate; @RequestMapping("/test")
public String freemarker(Map<String,Object> map){
map.put("name", "警察叔叔");
//三个人的信息
People p1 = new People("Ninja400",10,12580.01f,null,null);
People p2 = new People("Ninja650",20,12580.01f,null,null);
People p3 = new People("Ninja250",30,12580.01f,null,null); //p1有两个好友 分别是p2 p3
List<People> friends = new ArrayList<>();
friends.add(p2);
friends.add(p3);
p1.setFriends(friends); //向Map中放入我的朋友们List
map.put("friends", friends); //三个人的信息采集
HashMap<String,People> peopleMap = new HashMap<>();
peopleMap.put("p1", p1);
peopleMap.put("p2", p2);
peopleMap.put("p3", p3); //全部People的信息和 我的信息
map.put("peopleMap",peopleMap);
map.put("p1", p1);
return "test1";
}
}

List指令--遍历List集合

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>FreemarkerTest1</title>
</head>
<body>
欢迎您:${name}!下面是我的同伙们!
<table>
<tr>
<td>序号</td>&nbsp;&nbsp;
<td>姓名</td>&nbsp;&nbsp;
<td>年龄</td>&nbsp;&nbsp;
<td>钱包</td>&nbsp;&nbsp;
</tr>
<#list friends as friend>
<tr>
<td>${friend_index + 1}</td>
<td>${friend.username}</td>
<td>${friend.age}</td>
<td>${friend.money}</td>
</tr>
</#list>
</table>
</body>
</html>
  • <#list friends as friend> 使用list指令遍历friends集合并将获得的每个值赋值给friend

  • _index:得到循环的下标,从0开始

map指令--遍历Map

 输出p1的信息<br/>
姓名:${p1.username}<br/>
年龄:${p1.age}<br/>
遍历输出p1、p2、p3的信息<br/>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
<#list peopleMap?keys as k>
<tr>
<td>${k_index + 1}</td>
<td>${peopleMap[k].username}</td>
<td>${peopleMap[k].age}</td>
<td >${peopleMap[k].money}</td>
</tr>
</#list>
</table>
  • ${p1.username} :如果参数是在我们的形参中,当存如后可通过Map的主键这样获取

  • <#list peopleMap?keys as k> 遍历这个Map,指定主键用K表示

if指令--逻辑判断

<table>
<tr>
<td>序号</td>&nbsp;&nbsp;
<td>姓名</td>&nbsp;&nbsp;
<td>年龄</td>&nbsp;&nbsp;
<td>钱包</td>&nbsp;&nbsp;
</tr>
<#list friends as friend>
<tr>
<td>${friend_index + 1}</td>
<td <#if friend.username == 'Ninja250'> style="background: dodgerblue" </#if>>${friend.username}</td>
<td>${friend.age}</td>
<td>${friend.money}</td>
</tr>
</#list>
</table>
  • <td <#if friend.username == 'Ninja250'> style="background: dodgerblue" </#if>>${friend.username}</td>

  • 如果遍历得到的对象的username属性是 Ninja250,该行的背景色显示为蓝色

运算符

FreeMarker支持的算术运算符包括:+、 - 、 * 、 / 、 % 2

逻辑运算符有如下几个: 逻辑与:&& 逻辑或:|| 逻辑非:! 逻辑运算符只能作用于布尔值,否则将产生错误

比较运算符 表达式中支持的比较运算符有如下几个:

  • 1 =或者==:判断两个值是否相等.

  • 2 !=:判断两个值是否不等.

  • 3 >或者gt:判断左边值是否大于右边值

  • 4 >=或者gte:判断左边值是否大于等于右边值

  • 5 <或者lt:判断左边值是否小于右边值

  • 6 <=或者lte:判断左边值是否小于等于右边值

注意:

  • =和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且 FreeMarker是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)>

空值处理

  • 判断某变量是否存在使用: xx??,如下,

  • <#if friends??>:为了防止friends为空报错可以加一个预判断,返回boolean

     <#if friends??>
<#list friends as friend>
<tr>
<td>${friend_index + 1}</td>
<td <#if friend.username == 'Ninja250'> style="background: dodgerblue" </#if>>${friend.username}</td>
<td>${friend.age!""}</td>
<td>${friend.money}</td>
</tr>
</#list>
</#if>
  • <td>${friend.age!""}</td> :当这个对象的age属性为空时,使用缺失变量默认为空字符串 “”

  • 使用!一定要指定一个默认值,当我们的属性存在多层嵌套时,可以用括号括起来,比如:

  • ${(p1.bestPeople.name)!''} :如果p1最好的朋友的name这个属性为空,用空字符串表示

内建函数

内建函数语法格式:变量 + ? + 函数名称

某个集合的大小:

我有${friends?size}个同伙!

日期格式化:

map.put("now", new Date());
显示年月日: ${now?date} <td/>
显示时分秒:${now?time} <td/>
显示日期+时间:${now?datetime} <td/>
自定义格式化: ${now?string("yyyy年MM月")}

内建函数

map.put("point",123456789);

当point是数字型,使用${point}会显示这个数字的值,默认每隔三位使用逗号分隔。 如果不想显示为每三位分隔的数字,可以使用c函数将数字型转成字符串输出

我们的座机号码是:<br>
${point} <br>
${point?c} <br>

将Json字符串撰文对象

<#assign text="{'name':'挽起袖子的年轻人','address':'四川省成都市成华区动物园单身狗圈养处'}" />
<#assign data=text?eval />
我是谁:${data.name} 地址:${data.address}

assign标签,assign的作用是定义一个变量。

FreeMarker简单入门到使用的更多相关文章

  1. FreeMarker 快速入门

    FreeMarker 快速入门 FreeMarker是一个很值得去学习的模版引擎.它是基于模板文件生成其他文本的通用工具.本章内容通过如何使用FreeMarker生成Html web 页面 和 代码自 ...

  2. 用IntelliJ IDEA创建Gradle项目简单入门

    Gradle和Maven一样,是Java用得最多的构建工具之一,在Maven之前,解决jar包引用的问题真是令人抓狂,有了Maven后日子就好过起来了,而现在又有了Gradle,Maven有的功能它都 ...

  3. [原创]MYSQL的简单入门

    MYSQL简单入门: 查询库名称:show databases; information_schema mysql test 2:创建库 create database 库名 DEFAULT CHAR ...

  4. Okio 1.9简单入门

    Okio 1.9简单入门 Okio库是由square公司开发的,补充了java.io和java.nio的不足,更加方便,快速的访问.存储和处理你的数据.而OkHttp的底层也使用该库作为支持. 该库极 ...

  5. emacs最简单入门,只要10分钟

    macs最简单入门,只要10分钟  windwiny @2013    无聊的时候又看到鼓吹emacs的文章,以前也有几次想尝试,结果都是玩不到10分钟就退出删除了. 这次硬着头皮,打开几篇文章都看完 ...

  6. 【java开发系列】—— spring简单入门示例

    1 JDK安装 2 Struts2简单入门示例 前言 作为入门级的记录帖,没有过多的技术含量,简单的搭建配置框架而已.这次讲到spring,这个应该是SSH中的重量级框架,它主要包含两个内容:控制反转 ...

  7. Docker 简单入门

    Docker 简单入门 http://blog.csdn.net/samxx8/article/details/38946737

  8. Springmvc整合tiles框架简单入门示例(maven)

    Springmvc整合tiles框架简单入门示例(maven) 本教程基于Springmvc,spring mvc和maven怎么弄就不具体说了,这边就只简单说tiles框架的整合. 先贴上源码(免积 ...

  9. git简单入门

    git简单入门 标签(空格分隔): git git是作为程序员必备的技能.在这里就不去介绍版本控制和git产生的历史了. 首先看看常用的git命令: git init git add git comm ...

随机推荐

  1. React 使用antd 清空表单

    handleResetClick = e => { this.props.form.resetFields();};

  2. SqlServer 查询的时候过滤条件有参数导致速度很慢的问题-参数嗅探

    何谓SQLSERVER参数嗅探 大家听到“嗅探”这个词应该会觉得跟黑客肯定有关系吧,使用工具嗅探一下参数,然后截获,脱裤o(∩_∩)o . 事实上,我觉得大家太敏感了,其实这篇文章跟数据库安全没有什么 ...

  3. 深入理解Magento – 第十章、十一章(英文原版地址,仅供参考)

    深入理解Magento – 第十章 – Magento系统覆盖和升级 http://alanstorm.com/magento_upgrade_rewrite_override 深入理解MAGENTO ...

  4. 【dart学习】-- Dart之元数据

    一,概述 元数据概述  元数据(Metadata),又称中介数据.中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置.历 ...

  5. 管理员技术(五): 配置文档的访问权限、 配置附加权限、绑定到LDAP验证服务、配置LDAP家目录漫游

    一.配置文档的访问权限 问题: 本例要求将文件 /etc/fstab 拷贝为 /var/tmp/fstab,并调整文件 /var/tmp/fstab的权限,满足以下要求: 1>  此文件的拥有者 ...

  6. Linux shell脚本编程if语句的使用方法(条件判断)

    if 语句格式if  条件then Commandelse Commandfi        别忘了这个结尾If语句忘了结尾fitest.sh: line 14: syntax error: unex ...

  7. PHP反序列化漏洞研究

    序列化 序列化说通俗点就是把一个对象变成可以传输的字符串 php serialize()函数 用于序列化对象或数组,并返回一个字符串.序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型和结 ...

  8. 兼容软件,Wine安装,Crossover安装,

    EL6 (RHEL6 and SL6) Required packages for proper building of 32-bit Wine on 64-bit EL6 yum install - ...

  9. nodejs 内存泄漏

    This looks OK at first glance. We could think that theThing get's overwritten with every invocation ...

  10. ElasticSearch Roaring bitmap 和跳表联合查询

    ElasticSearch Roaring map 先把所有数按65535划分, 划分方法就是求商和余数,商代表数字最终在哪一块,余数代表最终在块内的数字 比如 1, 65536, 65537, 13 ...