FreeMarker 快速入门

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

1 简介

FreeMarker是一款用java语言编写的模版引擎,它虽然不是web应用框架,但它很合适作为web应用框架的一个组件。

特点:

1. 轻量级模版引擎,不需要Servlet环境就可以很轻松的嵌入到应用程序中

2. 能生成各种文本,如html,xml,java,等

3. 入门简单,它是用java编写的,很多语法和java相似

工作原理:(借用网上的图片)

2 FreeMarker 程序

这里通过模拟简单的代码自动生产工具来感受第一个FreeMarker程序。

项目目录结构

项目创建流程

第一步:创建一个maven项目导入 FreeMarker jar 包

第二步:创建目录templates,并创建一个 FreeMarker模版文件 hello.ftl

第三步:创建一个运行FreeMarker模版引擎的 FreeMarkerDemo.java 文件

第四步:运行main方法后刷新项目

pom.xml 文件 ,maven 项目核心文件,管理 jar 包。

 <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.freemark</groupId>
<artifactId>freemarkerStudy</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging> <dependencies>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.20</version>
</dependency>
</dependencies> </project>

hello.ftl  FreeMarker基本语法: ${xxx} xxx 相当于占位符,java后台给xxx赋值后,再通过${}输出

 package ${classPath};

 public class ${className} {

     public static void main(String[] args) {
System.out.println("${helloWorld}");
} }

FreeMarkerDemo.java 核心方法,使用 FreeMarker 模版引擎。

 package com.freemark.hello;

 import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map; import freemarker.template.Configuration;
import freemarker.template.Template; /**
* 最常见的问题:
* java.io.FileNotFoundException: xxx does not exist. 解决方法:要有耐心
* FreeMarker jar 最新的版本(2.3.23)提示 Configuration 方法被弃用
* 代码自动生产基本原理:
* 数据填充 freeMarker 占位符
*/
public class FreemarkerDemo { private static final String TEMPLATE_PATH = "src/main/java/com/freemark/hello/templates";
private static final String CLASS_PATH = "src/main/java/com/freemark/hello"; public static void main(String[] args) {
// step1 创建freeMarker配置实例
Configuration configuration = new Configuration();
Writer out = null;
try {
// step2 获取模版路径
configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
// step3 创建数据模型
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("classPath", "com.freemark.hello");
dataMap.put("className", "AutoCodeDemo");
dataMap.put("helloWorld", "通过简单的 <代码自动生产程序> 演示 FreeMarker的HelloWorld!");
// step4 加载模版文件
Template template = configuration.getTemplate("hello.ftl");
// step5 生成数据
File docFile = new File(CLASS_PATH + "\\" + "AutoCodeDemo.java");
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
// step6 输出文件
template.process(dataMap, out);
System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^AutoCodeDemo.java 文件创建成功 !");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != out) {
out.flush();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
} }

运行程序后刷新项目,会发现多了一个AutoCodeDemo.java类。不仅仅是java类,xml也是可以。笔者就是通过FreeMarker做了一个简易的工具类,公司的一个标准管理页面及其增删改查等功能,以及相关的配置文件(十三个文件),一个回车就全部自动生成(偷懒ing)。

3 FreeMarker 语法

语法和java很类似,其中宏的概念可能比较陌生,先上代码

stringFreeMarker.ftl  FreeMarker主要核心知识点

字符串输出:
${"Hello ${name} !"} / ${"Hello " + name + " !"}
<#assign cname=r"特殊字符完成输出(http:\www.baidu.com)">
${cname} 字符串截取 :
通过下标直接获取下标对应的字母: ${name[]}
起点下标..结尾下标截取字符串:${name[0..5]} 算数运算:
<#-- 支持"+"、"-"、"*"、"/"、"%"运算符 -->
<#assign number1 = 10>
<#assign number2 = 5>
"+" : ${number1 + number2}
"-" : ${number1 - number2}
"*" : ${number1 * number2}
"/" : ${number1 / number2}
"%" : ${number1 % number2} 比较运算符:
<#if number1 + number2 gte 12 || number1 - number2 lt 6>
"*" : ${number1 * number2}
<#else>
"/" : ${number1 / number2}
</#if> 内建函数:
<#assign data = "abcd1234">
第一个字母大写:${data?cap_first}
所有字母小写:${data?lower_case}
所有字母大写:${data?upper_case}
<#assign floatData = 12.34>
数值取整数:${floatData?int}
获取集合的长度:${users?size}
时间格式化:${dateTime?string("yyyy-MM-dd")} 空判断和对象集合:
<#if users??>
<#list users as user >
${user.id} - ${user.name}
</#list>
<#else>
${user!"变量为空则给一个默认值"}
</#if> Map集合:
<#assign mapData={"name":"程序员", "salary":15000}>
直接通过Key获取 Value值:${mapData["name"]}
通过Key遍历Map:
<#list mapData?keys as key>
Key: ${key} - Value: ${mapData[key]}
</#list>
通过Value遍历Map:
<#list mapData?values as value>
Value: ${value}
</#list> List集合:
<#assign listData=["ITDragon", "blog", "is", "cool"]>
<#list listData as value>${value} </#list> include指令:
引入其他文件:<#include "otherFreeMarker.ftl" /> macro宏指令:
<#macro mo>
定义无参数的宏macro--${name}
</#macro>
使用宏macro: <@mo />
<#macro moArgs a b c>
定义带参数的宏macro-- ${a+b+c}
</#macro>
使用带参数的宏macro: <@moArgs a=1 b=2 c=3 /> 命名空间:
<#import "otherFreeMarker.ftl" as otherFtl>
${otherFtl.otherName}
<@otherFtl.addMethod a=10 b=20 />
<#assign otherName="修改otherFreeMarker.ftl中的otherName变量值"/>
${otherFtl.otherName}
<#assign otherName="修改otherFreeMarker.ftl中的otherName变量值" in otherFtl />
${otherFtl.otherName}

otherFreeMarker.ftl 为了测试命名空间 和 include 指令的FreeMarker文件

其他FreeMarker文件
<#macro addMethod a b >
result : ${a + b}
</#macro>
<#assign otherName="另外一个FreeMarker的变量">

FreeMarkerDemo.java 核心方法

 package com.freemark.demo;

 import java.util.List;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map; import freemarker.template.Configuration;
import freemarker.template.Template; public class FreeMarkerDemo { private static final String TEMPLATE_PATH = "src/main/java/com/freemark/demo/templates"; public static void main(String[] args) {
// step1 创建freeMarker配置实例
Configuration configuration = new Configuration();
Writer out = null;
try {
// step2 获取模版路径
configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH));
// step3 创建数据模型
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("name", "itdragon博客");
dataMap.put("dateTime", new Date()); List<User> users = new ArrayList<User>();
users.add(new User(1, "ITDragon 博客"));
users.add(new User(2, "欢迎"));
users.add(new User(3, "You!"));
dataMap.put("users", users);
// step4 加载模版文件
Template template = configuration.getTemplate("stringFreeMarker.ftl");
// step5 生成数据
out = new OutputStreamWriter(System.out);
// step6 输出文件
template.process(dataMap, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != out) {
out.flush();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
} }

User.java 为了测试 FreeMarker的集合对象

 package com.freemark.demo;

 public class User {

     private Integer id;
private String name; public User() {
} public User(Integer id, String name) {
this.id = id;
this.name = name;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
} }

最后的打印结果

字符串输出:
Hello itdragon博客 ! / Hello itdragon博客 !
特殊字符完成输出(http:\www.baidu.com) 字符串截取 :
通过下标直接获取下标对应的字母: d
起点下标..结尾下标截取字符串:itdrag 算数运算:
"+" : 15
"-" : 5
"*" : 50
"/" : 2
"%" : 0 比较运算符:
"*" : 50 内建函数:
第一个字母大写:Abcd1234
所有字母小写:abcd1234
所有字母大写:ABCD1234
数值取整数:12
获取集合的长度:3
时间格式化:2017-10-29 空判断和对象集合:
1 - ITDragon 博客
2 - 欢迎
3 - You! Map集合:
直接通过Key获取 Value值:程序员
通过Key遍历Map:
Key: name - Value: 程序员
Key: salary - Value: 15,000
通过Value遍历Map:
Value: 程序员
Value: 15,000 List集合:
ITDragon blog is cool include指令:
其他FreeMarker文件 macro宏指令:
使用宏macro: 定义无参数的宏macro--itdragon博客
使用带参数的宏macro: 定义带参数的宏macro-- 6 命名空间:
另外一个FreeMarker的变量
result : 30
另外一个FreeMarker的变量
修改otherFreeMarker.ftl中的otherName变量值

语法详解

数据类型

和java不同,FreeMarker不需要定义变量的类型,直接赋值即可。

字符串: value = "xxxx" 。如果有特殊字符 string = r"xxxx" 。单引号和双引号是一样的。

数值:value = 1.2。数值可以直接等于,但是不能用科学计数法。

布尔值:true or  false。

List集合:list = [1,2,3] ; list=[1..100] 表示 1 到 100 的集合,反之亦然。

Map集合:map = {"key" : "value" , "key2" : "value2"},key 必须是字符串哦!

实体类:和EL表达式差不多,直接点出来。

字符串操作

字符串连接:可以直接嵌套${"hello , ${name}"} ; 也可以用加号${"hello , " + name}

字符串截取:string[index]。index 可以是一个值,也可以是形如 0..2 表示下标从0开始,到下标为2结束。一共是三个数。

比较运算符

== (等于),!= (不等于),gt(大于),gte(大于或者等于),lt(小于),lte(小于或者等于)。不建议用 >,<  可能会报错!

一般和 if 配合使用

内建函数

FreeMarker 提供了一些内建函数来转换输出,其结构:变量?内建函数,这样就可以通过内建函数来转换输出变量。

1. html: 对字符串进行HTML编码;
2. cap_first: 使字符串第一个字母大写;
3. lower_case: 将字符串转成小写;
4. upper_case: 将字符串转成大写;
5. size: 获得集合中元素的个数;
6. int: 取得数字的整数部分。

变量空判断

!    指定缺失变量的默认值;一般配置变量输出使用
??    判断变量是否存在。一般配合if使用 <#if value??></#if>

宏指令

可以理解为java的封装方法,供其他地方使用。宏指令也称为自定义指令,macro指令

语法很简单:<#macro val > 声明macro </#macro>; 使用macro <@val />

命名空间

可以理解为java的import语句,为避免变量重复。一个重要的规则就是:路径不应该包含大写字母,使用下划线_分隔词语,myName --> my_name

语法很简单:<#import "xxx.ftl" as val>

其他没有说明的语法是因为和java一样,没什么特别之处。所以没有列出来。

4 FreeMarker Web

这里是和SpringMVC整合的,SpringMVC的配置就不多说了,笔者也写过相关的文章,同时也会提供源码

导入相关的jar pom.xml

<!-- freeMarker start -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
</dependencies>
<!-- freeMarker end -->

springmvc的配置文件:

<!-- 整合Freemarker -->
<!-- 放在InternalResourceViewResolver的前面,优先找freemarker -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/views/templates"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
<property name="contentType" value="text/html; charset=UTF-8"/>
</bean>

Controller 层

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; @Controller
public class HelloFreeMarkerController { @RequestMapping("/helloFreeMarker")
public String helloFreeMarker(Model model) {
model.addAttribute("name","ITDragon博客");
return "helloFreeMarker";
} }

最后是Freemarker文件

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>FreeMarker Web</title>
</head>
<body>
<h1>Hello ${name} !</h1>
</body>
</html>

源码地址:https://gitee.com/itdragon/springmvc

5 小结

1. 知道了FreeMarker是一块模版引擎,可以生产xml,html,java等文件

2. 知道了FreeMarker文件提供占位符,java文件提供数据,通过FreeMarker模版引擎生产有数据的页面,文中是将数据放在Map中。web应用可以用setter/getter 方法

3. 知道了FreeMarker语法中字符串的显示特殊字符,截取的操作。以及一些内置方法的使用

4. 重点了解FreeMarker的空判断知识点。判断变量是否为空用 "??" ,如果变量为空设置默认值。如果不注意空问题,可能会出现黄色页面的提示哦!

5. FreeMarker的宏概念,命名空间,引入文件,给变量赋值,集合的遍历等。

6. Freemarker 整合SpringMVC。

到这里FreeMarker的入门就结束了,是不是很简单。如果有什么不对的地方,请指正!

FreeMarker 快速入门的更多相关文章

  1. springboot2.0整合freemarker快速入门

    目录 1. 快速入门 1.1 创建工程pom.xml文件如下 1.2 编辑application.yml 1.3 创建模型类 1.4 创建模板 1.5 创建controller 1.6 测试 2. F ...

  2. FreeMarker快速入门

    虽然当前比较推荐使用thymeleaf替代jsp作为java网页开发的模板语言,不过公司推荐使用freemarker,那就顺势而为,速度学一发,然后迅速开始新项目了. 简介 FreeMarker第一个 ...

  3. 【JavaWeb】FreeMarker快速入门

    FreeMarker Freemarker是免费开源的模板引擎技术: Freemarker脚本为Freemarker Template Language: Freemarker提供了大量内建函数来简化 ...

  4. 【FreeMarker】FreeMarker快速入门(一)

    什么是 FreeMarker FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具. 它不是面向最终用户 ...

  5. SpringMvc_快速入门,深入分析

    目录  一.前言二.spring mvc 核心类与接口三.spring mvc 核心流程图 四.spring mvc DispatcherServlet说明 五.spring mvc 父子上下文的说明 ...

  6. Spring MVC 教程,快速入门,深入分析

    http://elf8848.iteye.com/blog/875830/ Spring MVC 教程,快速入门,深入分析 博客分类: SPRING Spring MVC 教程快速入门  资源下载: ...

  7. Spring_MVC_教程_快速入门_深入分析

    Spring MVC 教程,快速入门,深入分析 博客分类: SPRING Spring MVC 教程快速入门  资源下载: Spring_MVC_教程_快速入门_深入分析V1.1.pdf Spring ...

  8. Thymeleaf【快速入门】

    前言:突然发现自己给自己埋了一个大坑,毕设好难..每一个小点拎出来都能当一个小题目(手动摆手..),没办法自己选的含着泪也要把坑填完..先一点一点把需要补充的知识学完吧.. Thymeleaf介绍 稍 ...

  9. Spring Boot 2.0 的快速入门(图文教程)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! Spring Boot 2.0 的快速入门(图文教程) 大家都 ...

随机推荐

  1. VisualStudio 合并代码文件

    如果有相同的类,一般可以使用 partial 让他写在多个文件,那么如何把多个文件合并?请看 MainWindow.xaml 和 MainWindow.xaml.cs 其中 代码文件被折叠,那么如何做 ...

  2. Web安全学习笔记(一)

    Web安全学习笔记(一): URL协议 HTTP协议 1. URL 2. HTTP协议 什么是HTTP HTTP的工作原理 HTTP报文 什么是Cookies HTTP请求方式 Referer请求的功 ...

  3. 聊聊Vue.js组件间通信的几种姿势

    写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出. 文章的原地址:https://github.com/a ...

  4. C# To JAVA Converter Cracked ( 破解版 )

    C# To JAVA Converter v17.10.6  Cracked by X-Cracker 简介 C# To Java converter是一款将C#代码片段或者C#项目转换为JAVA的工 ...

  5. 使用EF操作Mysql数据库中文变问号的解决方案

    问题场景:使用Entity Framework 6.0 操作Mysql数据库,中文保存至数据库后全部变成问号.但是使用Mysql API却不会. 原因排查:首先想到的肯定是数据库编码问题,一次查询了表 ...

  6. call()与apply() 改变this指向

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Consolas; color: #a5b2b9 } span.Apple-tab-span ...

  7. C++流类库(11)

    C++的流类库由几个进行I/O操作的基础类和几个支持特定种类的源和目标的I/O操作的类组成. 流类库的基础类 ios类是isrream类和ostream类的虚基类,用来提供对流进行格式化I/O操作和错 ...

  8. 使用原生php读写excel文件

    最近在工作中遇到一个需求,需要将数据库中的数据导出到excel文件中,并下载excel文件.因为以前没做过,所以就百度了一下, 网上说的大多是使用PHPExcel类来操作excel文件,这还要去下载这 ...

  9. aapt不是内部命令

    解决方法:在E:\sdk\build-tools\目录下的任意文件夹下查找aapt,复制到E:\sdk\platform-tools,具体盘符是情况而定,如果还不行,尝试配置环境变量!

  10. Java基础笔记8

    Object类 Object类是所有类的父类. 如果某个类没有显示的继承某个父类,那么该类则继承Object. 类 Object 是类层次结构的根类.每个类都使用 Object 作为超类. 所有对象( ...