1.Introduction
visit http://freemarker.sourceforge.net/ for more information.
2.Maven Dependency
<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>org.fool.freemarker</groupId> <artifactId>freemarker</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>freemarker</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.19</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> </project>
3.Project Directory
4.FreemarkerUtil
package org.fool.freemarker.util; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; public class FreemarkerUtil { public Template getTemplate(String name) { Template template = null; try { // 通过Freemaker的Configuration读取相应的ftl Configuration cfg = new Configuration(); // 设定去哪里读取相应的ftl模板文件 cfg.setClassForTemplateLoading(this.getClass(), "/ftl"); // 在模板文件目录中找到名称为name的文件 template = cfg.getTemplate(name); } catch (IOException e) { e.printStackTrace(); } return template; } public void print(String name, Map<String, Object> root) { try { // 通过Template可以将模板文件输出到相应的流 Template template = this.getTemplate(name); template.process(root, new PrintWriter(System.out)); } catch (TemplateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void fprint(String name, Map<String, Object> root, String outFile) { FileWriter out = null; try { out = new FileWriter(new File(outFile)); Template template = this.getTemplate(name); template.process(root, out); out.flush(); } catch (IOException e) { e.printStackTrace(); } catch (TemplateException e) { e.printStackTrace(); } finally { try { if (out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
5.基本使用
User.java
package org.fool.freemarker.model; public class User { private int id; private String name; private int age; private Group group; public User() { } public User(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Group getGroup() { return group; } public void setGroup(Group group) { this.group = group; } }
Group.java
package org.fool.freemarker.model; public class Group { private String name; public Group() { } public Group(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Student.java
package org.fool.freemarker.model; public class Student { private String no; private String name; public Student() { } public Student(String no, String name) { this.no = no; this.name = name; } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Article.java
package org.fool.freemarker.model; public class Article { private String title; private Channel channel; public Article() { } public Article(String title, Channel channel) { this.title = title; this.channel = channel; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Channel getChannel() { return channel; } public void setChannel(Channel channel) { this.channel = channel; } }
Channel.java
package org.fool.freemarker.model; public class Channel { private int id; private String name; public Channel(int id, String name) { this.id = id; this.name = name; } public Channel() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
TestFreemarker.java
package org.fool.freemarker.test; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.fool.freemarker.model.Article; import org.fool.freemarker.model.Channel; import org.fool.freemarker.model.Student; import org.fool.freemarker.model.User; import org.fool.freemarker.util.FreemarkerUtil; import org.junit.Before; import org.junit.Test; public class TestFreemarker { FreemarkerUtil fu = null; // 创建数据模型 Map<String, Object> root = null; @Before public void setUp() { fu = new FreemarkerUtil(); root = new HashMap<>(); } @Test public void test0102() { // 为数据模型添加值 root.put("username", "Hero"); // 将数据模型和模板组合的数据输出到控制台 fu.print("01.ftl", root); fu.fprint("02.ftl", root, "01.html"); } @Test public void test03() { root.put("user", new User(1, "Hero", 16)); sprint("03.ftl"); fprint("03.ftl", "03.html"); } @Test public void test04() { List<User> users = Arrays.asList(new User(1, "Hero", 16), new User(1, "Heroine", 18)); root.put("users", users); sprint("04.ftl"); fprint("04.ftl", "04.html"); } @Test public void test05() { List<User> users = Arrays.asList(new User(1, "Hero", 16), new User(1, "Heroine", 18)); root.put("username", "admin"); root.put("users", users); sprint("05.ftl"); fprint("05.ftl", "05.html"); } @Test public void test06() { // 此时user对象并没有group的值,这时如果在页面显示group直接报错 // freemarker不会处理空值 root.put("user", new User(1, "Hero", 16)); sprint("06.ftl"); fprint("06.ftl", "06.html"); } @Test public void test07() { root.put("now", new Date()); root.put("username", "Hero"); sprint("07.ftl"); fprint("07.ftl", "07.html"); } @Test public void test08() { sprint("08.ftl"); } @Test public void test09() { sprint("09.ftl"); } @Test public void test10() { root.put("username", "Hero"); sprint("10.ftl"); } @Test public void test11() { sprint("11.ftl"); } @Test public void test12() { List<User> users = Arrays.asList(new User(1, "Hero", 22), new User(2, "Heroine", 33), new User(3, "HeroAndHeroine", 44)); root.put("users", users); List<Student> stus = Arrays.asList(new Student("12345", "Puck"), new Student("67890", "Doom")); root.put("stus", stus); sprint("12.ftl"); fprint("12.ftl", "12.html"); } @Test public void test13() { sprint("13.ftl"); fprint("13.ftl", "13.html"); } @Test public void test14() { Map<String, List<Article>> arts = new HashMap<String, List<Article>>(); List<Article> a1 = Arrays.asList( new Article("哈登上星!不是东道主也够格! 休城四年后再出明星", new Channel(1, "All Star")), new Article("ESPN新星榜哈登高居第4 最像希尔未来赶超滑翔机?", new Channel(1, "All Star")), new Article("哈登入选全明星实至名归 高富帅有望亮相新秀挑战赛", new Channel(1, "All Star")), new Article("诺天王连续11年全明星纪录终止 季后赛成首要目标", new Channel(1, "All Star")), new Article("欧文小霍首次入选接控卫大旗 两王牌后卫遗憾落选", new Channel(1, "All Star")), new Article("巴克利炮轰全明星替补名单:库里没进头要气炸了!", new Channel(1, "All Star"))); List<Article> a2 = Arrays.asList( new Article("魔兽右肩复查伤情无大碍 明天主场战爵士继续出战", new Channel(1, "LAL")), new Article("湖人5大悲催看点:科比数据年≠成功 四巨头瓦解?", new Channel(1, "LAL")), new Article("湖人名宿气炸:这队正走向灾难 死了!死了!都死了!", new Channel(1, "LAL")), new Article("湖人会议科比质问魔兽", new Channel(1, "LAL")), new Article("勇士主帅为库里落选鸣冤!:魔兽?他入选就是笑话", new Channel(1, "LAL")), new Article("湖人要哭的在后头 5连败打雷霆?还记得宝强那张神图", new Channel(1, "LAL"))); arts.put("1", a1); arts.put("2", a2); root.put("arts", arts); sprint("14.ftl"); fprint("14.ftl", "14.html"); } private void sprint(String name) { fu.print(name, root); } private void fprint(String name, String filename) { fu.fprint(name, root, filename); } }
将文件读写到html中
01.ftl
Hello:${username}
02.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>${username}</h1> </body> </html>
常用指令
03.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>${user.id}-----${user.name}-----${user.age}</h1> <#if user.age lt 12> ${user.name} is a teenager <#elseif user.age lt 18> ${user.name} is almost an adult <#else> ${user.name} is an adult </#if> </body> </html>
04.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#list users as user> ${user.id}---------${user.name}-------${user.age}<br/> </#list> </body> </html>
05.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#include "/inc/top.ftl"> <hr> <#list users as user> ${user.id}---------${user.name}-------${user.age}<br> </#list> </body> </html>
top.ftl
<h1>Welcome ${username}</h1>
空值的处理
06.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> ${user.id}---------${user.name}-------${user.group!}<br> <#-- ${user.group.name!} --> <#-- 按照以上的方式加! freemarker仅仅只会判断group.name是不是空值 --> ${(user.group.name)!"没有任何值存在"} ${(a.b)!"没有a.b元素"} <#if (a.b)??> 不为空 <#else> 为空 </#if> </body> </html>
基本数据类型
07.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#--定义变量--> <#assign username="Heroine" /> ${username} <#--定义了一个数字--> <#assign num=10 /> ${num+11} <#assign str="10" /> ${str+11} <#--值会完成覆盖--> <#assign str="33" /> ${str+11} <#assign b=true/> <#--不能直接输出数字或者字符串以外的类型,否则都会报错,需要转换为字符串才能输出 使用xxx?string可以完成对字符串的转换 --> <#--${b}--> ${b?string} ${(a.d)???string} <#--日期也不能直接输出,需要转换为字符串--> ${now?string("yyyy-MM-dd HH:mm:ss")} <#--${now?string}没有为日期设定格式也会报错--> <#--以下显示了使用字符链接和插值的方式连接字符串--> ${"hello "+username} ${"hello ${username}"} <#--字符串转换为日期 date用来转换日期,datetime用来转换日期和时间,time用来转换时间 --> <#assign bir1="2012-12-21 12:22:33"?date("yyyy-MM-dd HH:mm:ss") /> <#assign bir2="2000-01-01 12:22:33"?datetime("yyyy-MM-dd HH:mm:ss") /> ${bir1} ${bir2} ${"<br>"?html} [${"abcde"?left_pad(10,"--")}] ${1.4?string(0)} ${1.8?int} </body> </html>
序列和哈希表
08.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#assign nums=[1,3,4,56,33,43] /> ${nums?first} <#--特别注意,以下定义不使用[12..200]--> <#assign nums=12..200 /><#--定义了一个连续的序列从12到199--> <#--序列的拆分--> <#assign nums1=nums[1..10] /> <#list nums1 as num> ${num} </#list> ${"你好,你来了吗今天看书了吗!"[0..8]}... <#assign maps={"1":"Hero", "2":"Heroine"} /> ${maps["1"]} <#--以下代码可以将map的key转换为相应的序列--> <#assign keys=maps?keys /> <#list keys as key> ${key}---${maps[key]} <#assign users={"username":"Hero","password":"123"} /> ${users.username}---${users["password"]} </#list> </body> </html>
自定义指令
09.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#--对于hello这个自定义指令而言,hello后的都是参数,有两个参数一个是num一个是ok--> <#macro hello num ok> <#list 1..num as n> <h1>Hello${ok}${n}</h1> </#list> </#macro> <#--<@hello/>会报错,因为hello有两个参数,在定义参数的值的时候参数名不能省略--> <@hello num=3 ok="World"/> <#--为repeat的两个参数定义了初始值,此时在调用该指令就可以省略参数,如果省略会使用默认值--> <#macro repeat num=10 ok="World"> <#list 1..num as n> <h1>Hello${ok}${n}</h1> </#list> </#macro> <@repeat/> <#macro test> <#--nested会输出指令中的内容--> <#nested 12 33/> <#nested 11 22/> <#nested 22 33/> </#macro> <@test;x,y> <h1>你好啊--${x}--${y}</h1> </@test> </body> </html>
10.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#--此时模板中的变量的名称和模型中的变量名称一致,不是覆盖,而是隐藏--> <#assign username="Heroine" /> ${username} <#--使用.globals可以访问模型中的变量--> ${.globals.username} <#macro test> <#--此时当调用该指令之后,会将模板中的变量username覆盖为王五 所以这种方式存在风险,所以一般不使用这种方式在指令中定义变量--> <#--<#assign username="HeroAndHeroine">--> <#--使用local可以声明局部变量,所以在marco中非特殊使用局部变量--> <#local username="HeroAndHeroine"> ${username} </#macro> <@test/> ${username} <#list 1..3 as username> <#--循环中的变量出了循环就消失--> ${username} </#list> ${username} </body> </html>
11.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#-- 使用incldue可能会出现覆盖的问题,可以使用import来完成导入,并且加入名称空间 <#include "/inc/inc1.ftl"/> <#include "/inc/inc2.ftl"/> --> <#import "/inc/inc1.ftl" as inc1 /> <#import "/inc/inc2.ftl" as inc2 /> ${inc1.username} ${inc2.username} <#--将一个变量定义到名称空间中--> <#assign age=12 in inc2 /> ${inc2.age} <#--访问名称空间中的自定义指令--> <@inc1.test /> </body> </html>
inc1.ftl
<#assign username="Hero"> <#macro test> hello world </#macro>
inc2.ftl
<#assign username="Heroine">
实现通用select
12.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#import "/inc/select.ftl" as my/> <@my.select id="address" datas=["北京","天津","上海"]/> <@my.select id="sex" datas=["选择性别","男","女"] value="男"/> <@my.select id="username" datas=users key="id" text="name" headkey="-1" headtext="请选择用户"/> <@my.select id="stu" datas=stus key="no" text="name" headkey="-1" headtext="请选择学生"/> <@my.select id="sex" datas={"0":"男","1":"女"} value="1"/> </body> </html>
select.ftl
<#macro select id datas value="" key="" text="" headkey="" headtext=""> <select id="${id}" name="${id}"> <#if headkey!=""> <option value="${headkey}">${headtext}</option> </#if> <#if datas?is_hash_ex> <#local keys=datas?keys/> <#list keys as key> <#if key==value> <option value="${key}" selected="selected">${datas[key]}</option> <#else> <option value="${key}">${datas[key]}</option> </#if> </#list> <#else> <#list datas as data> <#if key!=""> <#if value==data[key]?string> <option value="${data[key]}" selected="selected">${data[text]}</option> <#else> <option value="${data[key]}">${data[text]}</option> </#if> <#else> <#if value==data> <option value="${data}" selected="selected">${data}</option> <#else> <option value="${data}">${data}</option> </#if> </#if> </#list> </#if> </select> </#macro>
实现通用分页
13.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#import "/inc/pager.ftl" as my /> <@my.pager url="#" totalPage=150 curPage=145 class="pagers" showPageNum=20 /> </body> </html>
pager.ftl
<#macro pager url totalPage curPage=1 class="" showPageNum=15> <#local halfPage=(showPageNum/2)?int/> <#if (halfPage>=curPage)> <@showPage start=1 end=curPage url=url class=class curPage=curPage/> <@showPage start=curPage+1 end=showPageNum curPage=curPage url=url class=class/> <#else> <@showPage start=curPage-halfPage end=curPage url=url class=class curPage=curPage/> <#if (curPage+halfPage>totalPage)> <#local endPage=totalPage/> <#else> <#local endPage=curPage+halfPage/> </#if> <@showPage start=curPage+1 end=endPage url=url class=class curPage=curPage/> </#if> </#macro> <#macro showPage start end curPage url class> <#list start..end as page> <#if curPage==page> [${page}] <#else> <a href="${url}" class="${class}">${page}</a> </#if> </#list> </#macro>
实现通用的文章显示
14.ftl
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#macro showArt cid titleNum> <#nested> <ul> <#local articles=arts[cid]/> <#list articles as art> <li><span><a href=""> <#if (art.title?length>titleNum)> ${art.title[0..titleNum]}... <#else> ${art.title} </#if> </a></span> </li> </#list> </ul> </#macro> <@showArt cid="1" titleNum=7> <h1>全明星替补名单公布</h1> </@showArt> <@showArt cid="2" titleNum=10> <h1>曝湖人不考虑交易魔兽</h1> </@showArt> </body> </html>
6.JUnit Tests
相关推荐
### FreeMarker编程指南知识点概述 #### 一、FreeMarker简介 FreeMarker是一个强大的模板引擎,主要用于根据提供的数据和模板生成输出文本。它可以用于多种场景,包括但不限于生成HTML页面、电子邮件、配置文件或...
- **创建模板文件**:在`resources/templates`目录下创建模板文件,例如`01-basic.ftl`,并在其中编写包含插值表达式的HTML代码。 ```html <!DOCTYPE html> <title>Hello World Example <h1>Hello ${name}!...
- 强大的整合能力:能够简单地整合第三方框架和组件,如FreeMarker、Velocity等。 - 高性能:设计上注重简洁高效的代码实现,对JSP/Servet API无过多封装,保证性能。 - 优秀的使用体验:设计上力求简单、完整、明确...
"jar for struts2 basic"指的是与Struts2基本功能相关的JAR库文件集合,这些文件是构建和运行Struts2应用的基础。在Java Web开发中,JAR(Java Archive)文件是用于打包类、资源和元数据的容器,便于代码重用和部署...
在本项目中,`freemarker-web`和`freemarker-hello`可能包含与Freemarker相关的配置和示例代码。 3. **模块化设计** 文件名如`cms-topic`、`cms-user`、`cms-core`、`basic-common`、`basic-hibernate`、`cms-web`...
3. **模板引擎**:JSP中的模板引擎如FreeMarker或Velocity,可以用来动态生成HTML页面,根据不同的数据生成不同的页面布局。 4. **安全机制**:包括身份验证、授权和加密,以确保网站的安全性。例如,会话管理、...
3. Result:表示Action执行后的结果,可以是JSP、Freemarker模板或其他类型。 4. Interceptors(拦截器):用于增强Action的处理逻辑,如权限验证、日志记录等。 5. ValueStack:存储ActionContext中的值,供视图层...
- View Resolution:可以配置视图解析器,如 Thymeleaf、Freemarker 或者直接返回 JSON。 6. **数据库集成** - 数据源配置:通过 `spring.datasource` 配置数据源属性,如用户名、密码和连接池。 - JPA & ...
5. **模板引擎**:JSP中的自定义标签库(Tag Libraries)或者现代的模板引擎如FreeMarker、Velocity,可能会被用来实现页面模板的复用和分离视图逻辑,提高代码的可维护性和可读性。 6. **安全性和性能**:在实际...
- `src/main/resources`:存放资源文件,如配置文件、静态内容(如 HTML、CSS、JS)和模板文件(如 Thymeleaf 或 FreeMarker)。 - `pom.xml` 或 `build.gradle`:构建文件,定义项目依赖和构建过程。 - `README.md`...
Spring MVC支持多种视图技术,如JSP、Thymeleaf、FreeMarker等。你可以使用ModelAndView或Model对象将数据传递给视图。 5. **ViewModel**:在实际应用中,模型和视图经常被组合在一起,形成ViewModel,它包含用于...
此外,可能还需要引入其他依赖,如`spring-boot-starter-web`来支持Web相关的功能,以及`spring-boot-starter-freemarker`来处理模板引擎。 配置文件`application.yml`中,可以设置Spring Security的相关参数,例如...
在Spring Boot应用中,通常会结合Thymeleaf或Freemarker这样的模板引擎来动态生成HTML响应。 6. **可能的架构**: - **前后端分离**: 博客系统可能采用了MVC(Model-View-Controller)模式,前端使用HTML、CSS和...
3. **Result**:结果是Action执行后向视图层返回的信息,它可以是简单的JSP页面,也可以是其他类型的视图技术,如FreeMarker或Velocity模板。 4. **Plug-in(插件)**:Struts2拥有丰富的插件系统,可以方便地集成...
这个“struts2_basic_lib”压缩包包含了Struts2框架运行所需的核心库文件,是进行Struts2开发的基础。 在Struts2框架中,`lib`目录下的库文件扮演着至关重要的角色,它们提供了框架的核心功能和依赖。以下是一些...
由产生内容 CoffeeScript [Common Lisp](#common lisp) 镖鹰长生不老药[Emacs Lisp](#emacs lisp) 埃尔朗FreeMarker GDScript 去盐酸HTML 车把哈斯克尔JavaJavaScript [Jupyter笔记本](#jupyter笔记本) ...
5. **模板技术**:Struts2支持多种视图技术,如JSP、FreeMarker、Velocity等,开发者可以根据需求选择合适的模板引擎。 现在,让我们关注压缩包中的具体文件。Struts2.0.11-lib通常会包含以下关键库文件: 1. `...
这通常包括Struts2的核心库、依赖的JAR文件,如Ognl、Freemarker、 Commons-logging等。开发者需要把这些JAR文件放入项目的类路径中,以便Struts2框架能够正常运行。 2. **web.xml配置**:在web应用的根目录下,web...
- springboot-basic - Spring Boot 基础知识,包括SpringBoot起步、配置详解、aop、filter、拦截器、监听、启动器、全局异常处理、外部Tomcat启动、HTTPS、监控 等。 - springboot-data - Spring Boot 数据库...
5. **freemarker.jar**:FreeMarker是一个模板引擎,用于生成动态内容,是Struts2默认的视图技术。 6. **xwork-core.jar**:XWork是Struts2的基础,提供了Action、拦截器等基础组件。 7. **其他依赖库**:如log4j...