FreeMarker学习总结
2018年10月22日 18:33:39 sunny2429 阅读数:5
FreeMarker简介
在java领域,表现层技术主要有三种:jsp、freemarker、velocity。
jsp是大家最熟悉的技术
优点:
1、功能强大,可以写java代码
2、支持jsp标签(jsp tag)
3、支持表达式语言(el)
4、官方标准,用户群广,丰富的第三方jsp标签库
5、性能良好。jsp编译成class文件执行,有很好的性能表现
缺点:jsp没有明显缺点,由于可以编写java代码,如使用不当容易破坏mvc结构。
velocity是较早出现的用于代替jsp的模板语言
优点:
1、不能编写java代码,可以实现严格的mvc分离
2、性能良好,据说比jsp性能还要好些
3、使用表达式语言,据说jsp的表达式语言就是学velocity的
缺点:
1、不是官方标准
2、用户群体和第三方标签库没有jsp多。
3、对jsp标签支持不够好
freemarker
优点:
1、不能编写java代码,可以实现严格的mvc分离
2、性能非常不错
3、对jsp标签支持良好
4、内置大量常用功能,使用非常方便
5、宏定义(类似jsp标签)非常方便
6、使用表达式语言
缺点:
1、不是官方标准
2、用户群体和第三方标签库没有jsp多
选择freemarker的原因:
1、性能。velocity应该是最好的,其次是jsp,普通的页面freemarker性能最差(虽然只是几毫秒到十几毫秒的差距)。但是在复杂页面上(包含大量判断、日期金额格式化)的页面上,freemarker的性能比使用tag和el的jsp好。
2、宏定义比jsp tag方便
3、内置大量常用功能。比如html过滤,日期金额格式化等等,使用非常方便
4、支持jsp标签
5、可以实现严格的mvc分离
FreeMarker是java的免费模板引擎,主要用于MVC中的view层,生成html展示数据给客户端,可以完全替代jsp。 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写,模板中没有业务逻辑,外部java程序通过数据库操作等生成数据传入template中, 然后输出页面。它能够生成各种文本:HTML、XML、JSP、RTF、Java源代码等等,而且不需要Servlet环境,并且可以从任何源载入模板,如本地文件、数据库等等。
FreeMarker插件下载
FreeMarker模板文件详解
1.注释
<#--注释内容-->
2.文本: 直接输出的部分,比如HTML标签及文本内容
3.插值:${ }或#{ }部分,使用数据模型中的数据代替,比如controller中model存储的数据
避免空值插值
!: 指定缺失变量的默认值
${sss!} <#--没有定义这个变量,默认值是空字符串! -->
${sss!"abc"} <#--没有定义这个变量,默认值是字符串abc! -->
??:判断变量是否存在
variable??,如果变量存在,返回true,否则返回false。
插值规则
a) 表达式放置在插值语法${}之中,用于输出表达式的值。
b) 表达式的值的类型可以是:字符串、 数字、布尔、日期时间、序列、Hash结构
c) 表达式支持Java中的所有运算符:
算术运算符:+、-、*、/、%
比较运算符:==(eq)、!=(ne)、>(gt)、>=(gte)、<(lt)、<=(lte)
逻辑运算符:&&(and)、||(or)、!(not)
三目运算符:? :
d) 内置函数:
Ⅰ) 使用方式:表达式?函数名[(实参)]
Ⅱ) 字符串的常用内置函数: substring(from[, to])、html、length、trim、url 示例:<#setting url_escaping_charset="UTF-8"> 、exp?url[("UTF-8")]
Ⅲ) 数字的常用内置函数:c、string[(数字模式串)]、
Ⅳ) 布尔的内置函数:string[("男", "女")]
Ⅴ) 内置的常用日期时间函数:string[("格式模式串")]、datetime、date、time
e) 序列:
在FTL中定义的序列:由方括号包括,各元素用英文逗号分隔如:<#assign seq=["winter", "spring", "summer", "autumn"]>也可以用数字范围(递增、反递增)定义数字序列: <#assign nums=101..105> 或 <#assign nums=105..101> 在数据模型中可以是List对象、Set对象,序列的常用内置函数:size、sort[("指定字段作排序依据")]
f) Hash结构:
在FTL文件中直接定义时:由大括号包括,由逗号分隔键/值列表,键和值之间用冒号分隔。键必须是字符串。如: <#assign scores={"语文":78, "数学":89, "英语":87}> ${scores.语文} 在数据模型中可以是Map对象,Hash结构的内置函数:size、keys、values
4.FTL指令:FreeMarker指令,和HTML标签类似,名字前加#予以区分,不会输出。
FTL指令详解:
assign 指令:用于为该模板页面创建或替换一个顶层变量。
-
<#--定义变量--> -
<#assign id=1 name="zhangsan" sex="男"> -
<#--定义数组--> -
<#assign hobbyArr=['篮球','足球','排球']> -
<#--定义Map集合--> -
<#assign people={"name":"mouse","age":25,"weight":140}>
if else 指令:做if判断用的。
-
<#assign age=20> -
<#if age gt 60>老年人 -
<#elseif age gt 40>中年人 -
<#elseif age gt 20>青年人 -
<#else> 少年人 -
</#if> -
<#if (age==20)> -
我今年20岁 -
</#if>
list 指令:主要是进行迭代服务器端传递过来的List集合。
item_index:当前变量的索引值
item_has_next:是否存在下一个对象
break:跳出迭代
-
<#list 1..9 as i> -
${i} -
</#list> -
<br/> -
<#list hobbyArr as hobby> -
下标:${hobby_index} -
值:${hobby}<br/> -
<#if !hobby_has_next> -
已经是最后一个 -
<#break> -
</#if> -
</#list> -
长度:${hobbyArr?size} -
<#--迭代Map集合--> -
<#assign keys = people?keys> <#--map的key集合--> -
<#list keys as key> -
${key} = ${h[key]} -
</#list>
switch 指令:作用类似于Java的switch语句。
-
<#assign age=10> -
<#switch age> -
<#case 0>0<#break> -
<#case 10>10<#break> -
<#case 20>20<#break> -
<#default>30 -
</#switch>
include 指令:用于导入文件,它可以在模版中插入其他的静态文件,或者是freemarker模版。
-
<#--parse=true 是否作为ftl语法解析,默认是true--> -
<#include "inc.ftl" encoding="UTF-8" parse=true>
import 指令:类似于java里的import,它导入文件,然后就可以在当前文件里使用被导入文件里的宏组件。
-
<#--访问时使用 inc.--> -
<#import "inc.ftl" as inc> -
${inc.name}
** noparse 指令:**noparse指令指定FreeMarker不处理该指定里包含的内容。
-
<#noparse> -
<#list hobbyArr as hobby> -
<tr><td>${hobby.name}<td><td>${hobby.age></td></tr> -
</#list> -
</#noparse>
macro 指令:用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令,类似于java中的方法,定义不会执行,调用才会执行,定义参数可以给默认值。
-
<#--定义--> -
<#macro name param1 param2 ... paramN> -
... -
<#nested loopvar1, loopvar2, ..., loopvarN> -
... -
<#return> -
... -
</#macro>
name : 指定的是该自定义指令的名字,使用自定义指令时可以传入多个参数
paramX : 指定使用自定义指令时报参数,使用该自定义指令时,必须为这些参数传入值
nested : 输出使用自定义指令时的中间部分
return : 可用于随时结束该自定义指令.
-
<#macro addCalc p1 p2=10> -
<#if p2=0 && p1=0> -
<return> -
</#if> -
输出结果为:${p1+p2} -
</#macro> -
<@addCalc p1=100 p2=200/> -
<@addCalc p1=10/>
macro包含nested的宏
-
<#macro myuser name> -
您的姓名是:${name}<br/> -
<#nested name?length> -
</#macro> -
<@myuser name='zs';len>名字长度:${len}</@myuser>
setting 指令:用于动态设置freeMarker的运行环境。
setting 指令:用于动态设置freeMarker的运行环境。
name的取值范围如下:
locale : 该选项指定该模板所用的国家/语言选项
number_format : 指定格式化输出数字的格式 ,number(数字)、currency(金额)、percent(百分数)三个值。
boolean_format : 指定两个布尔值的语法格式,默认值是true,false
date_format,time_format,datetime_format : 指定格式化输出日期的格式
time_zone : 设置格式化输出日期时所使用的时区
-
<#--setting设置--> -
<#setting locale="zh_CN"/> -
<#setting number_format="number"/> -
<#setting number_format="currency"/> -
<#setting number_format="percent"/> -
<#setting date_format="yyyy-MM-dd"/> -
<#setting time_format="HH:mm:ss"/> -
<#setting datetime_format="yyyy-MM-dd HH:mm:ss"/> -
<#setting time_zone="zzzz"> -
<#--string函数格式化--> -
<#assign answer=42/> -
${answer} -
${answer?string} -
${answer?string.number} -
${answer?string.currency} -
${answer?string.percent} -
<#--EEEE表示星期,MMMM中文月份,yy年份后二位,a(上、中、下午),zzzz时区--> -
${time?string("yyyy-MM-dd HH:mm:ss zzzz")} -
${time?string("EEE,MMM d,yy")} -
${time?string("EEEE,MMMM dd,yyyy,hh:mm:ss a '('zzz')'")}
Java代码读取ftl模板,输出页面
-
public class FreeMarkerUtil { -
@SuppressWarnings("deprecation") -
public Template getTemplate(String name){ -
Template temp = null; -
// 通过Freemarker的Configuration读取相应的FTL -
Configuration cfg = new Configuration(); -
// 设定去哪里读取相应的ftl模板 ,src/template/ -
cfg.setClassForTemplateLoading(this.getClass(), "/template"); -
try { -
// 在模板文件目录中寻找名称为name的模板文件 -
temp = cfg.getTemplate(name); -
} catch (IOException e) { -
e.printStackTrace(); -
} -
return temp; -
} -
/** -
* 控制台输出文件内容 -
* @param name -
* @param rootMap -
*/ -
public void print(String name,Map<String,Object> rootMap){ -
// 通过Template类可以将模板文件输出到相应的文件 -
Template temp = this.getTemplate(name); -
try { -
temp.process(rootMap, new PrintWriter(System.out)); -
} catch (TemplateException | IOException e) { -
e.printStackTrace(); -
} -
} -
/** -
* 将替换后的模板内容输出到文件 -
* @param name -
* @param rootMap -
* @param outFile -
*/ -
public void fprint(String name,Map<String,Object> rootMap,String outFile){ -
File file = null; -
try { -
//获取项目目录 -
file = new DefaultResourceLoader().getResource("").getFile(); -
while(true){ -
String fileName = file.getName(); -
file = file.getParentFile(); -
if("target".equals(fileName)||"src".equals(fileName)){ -
break; -
} -
} -
//获取模板生成文件位置 -
} catch (IOException e1) { -
e1.printStackTrace(); -
} -
String viewName = file+"/src/main/webapp/"; -
FileWriter out = null; -
try { -
out = new FileWriter(new File(viewName+outFile)); -
Template template = this.getTemplate(name); -
template.process(rootMap, out); -
} catch (IOException | TemplateException e) { -
e.printStackTrace(); -
}finally{ -
if(out != null){ -
try { -
out.close(); -
} catch (IOException e) { -
e.printStackTrace(); -
} -
} -
} -
} -
public static void main(String[] args) { -
Map<String,Object> rootMap = new HashMap<>(); -
FreeMarkerUtil freeMarkerUtil = new FreeMarkerUtil(); -
rootMap.put("time",new Date()); -
//freeMarkerUtil.print("inc.ftl", rootMap); -
freeMarkerUtil.fprint("inc.ftl", rootMap, "01.html"); -
} -
}
与springmvc整合
-
<?xml version="1.0" encoding="UTF-8"?> -
<beans xmlns="http://www.springframework.org/schema/beans" -
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -
xmlns:context="http://www.springframework.org/schema/context" -
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd -
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> -
<context:component-scan base-package="com.ftl.controller"></context:component-scan> -
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> -
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> -
<!-- 配置Freemarker属性文件路径 --> -
<bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> -
<property name="location" value="classpath:freemarker.properties" /> -
</bean> -
<!-- 配置freeMarker模板加载地址 --> -
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> -
<!-- 视图解析器在/tpl/路径下扫描视图文件 --> -
<property name="templateLoaderPath" value="/tpl/" /> -
<property name="freemarkerVariables"> -
<map> -
<entry key="xml_escape" value-ref="fmXmlEscape" /> -
</map> -
</property> -
<property name="freemarkerSettings"> -
<props> -
<!-- 模板编码格式 --> -
<prop key="default_encoding">UTF-8</prop> -
<!-- 本地化设置 --> -
<prop key="locale">UTF-8</prop> -
<!-- url转义编码 --> -
<prop key="url_escaping_charset">UTF-8</prop> -
</props> -
</property> -
</bean> -
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" /> -
<!-- 配置freeMarker视图解析器 --> -
<bean id="freemakerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> -
<property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> -
<!-- 扫描路径內所有以ftl結尾的文件 --> -
<property name="viewNames"> -
<array> -
<value>*.ftl</value> -
</array> -
</property> -
<property name="contentType" value="text/html; charset=UTF-8" /> -
<property name="exposeRequestAttributes" value="true" /> -
<property name="exposeSessionAttributes" value="true" /> -
<property name="exposeSpringMacroHelpers" value="true" /> -
<property name="requestContextAttribute" value="request" /> -
<!-- 给视图解析器配置优先級,你可以给之前jsp视图解析器的值配为2 --> -
<property name="order" value="1" /> -
</bean> -
</beans>