FreeMarker学习总结

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 指令:用于为该模板页面创建或替换一个顶层变量。

 
  1. <#--定义变量-->

  2. <#assign id=1 name="zhangsan" sex="男">

  3. <#--定义数组-->

  4. <#assign hobbyArr=['篮球','足球','排球']>

  5. <#--定义Map集合-->

  6. <#assign people={"name":"mouse","age":25,"weight":140}>

if else 指令:做if判断用的。

 
  1. <#assign age=20>

  2. <#if age gt 60>老年人

  3. <#elseif age gt 40>中年人

  4. <#elseif age gt 20>青年人

  5. <#else> 少年人

  6. </#if>

  7. <#if (age==20)>

  8. 我今年20岁

  9. </#if>

list 指令:主要是进行迭代服务器端传递过来的List集合。 
item_index:当前变量的索引值 
item_has_next:是否存在下一个对象 
break:跳出迭代

 
  1. <#list 1..9 as i>

  2. ${i}

  3. </#list>

  4. <br/>

  5. <#list hobbyArr as hobby>

  6. 下标:${hobby_index}

  7. 值:${hobby}<br/>

  8. <#if !hobby_has_next>

  9. 已经是最后一个

  10. <#break>

  11. </#if>

  12. </#list>

  13. 长度:${hobbyArr?size}

  14.  
  15. <#--迭代Map集合-->

  16. <#assign keys = people?keys> <#--map的key集合-->

  17. <#list keys as key>

  18. ${key} = ${h[key]}

  19. </#list>

switch 指令:作用类似于Java的switch语句。

 
  1. <#assign age=10>

  2. <#switch age>

  3. <#case 0>0<#break>

  4. <#case 10>10<#break>

  5. <#case 20>20<#break>

  6. <#default>30

  7. </#switch>

include 指令:用于导入文件,它可以在模版中插入其他的静态文件,或者是freemarker模版。

 
  1. <#--parse=true 是否作为ftl语法解析,默认是true-->

  2. <#include "inc.ftl" encoding="UTF-8" parse=true>

import 指令:类似于java里的import,它导入文件,然后就可以在当前文件里使用被导入文件里的宏组件。

 
  1. <#--访问时使用 inc.-->

  2. <#import "inc.ftl" as inc>

  3. ${inc.name}

** noparse 指令:**noparse指令指定FreeMarker不处理该指定里包含的内容。

 
  1. <#noparse>

  2. <#list hobbyArr as hobby>

  3. <tr><td>${hobby.name}<td><td>${hobby.age></td></tr>

  4. </#list>

  5. </#noparse>

macro 指令:用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令,类似于java中的方法,定义不会执行,调用才会执行,定义参数可以给默认值。

 
  1. <#--定义-->

  2.  
  3. <#macro name param1 param2 ... paramN>

  4. ...

  5. <#nested loopvar1, loopvar2, ..., loopvarN>

  6. ...

  7. <#return>

  8. ...

  9. </#macro>

name : 指定的是该自定义指令的名字,使用自定义指令时可以传入多个参数 
paramX : 指定使用自定义指令时报参数,使用该自定义指令时,必须为这些参数传入值 
nested : 输出使用自定义指令时的中间部分 
return : 可用于随时结束该自定义指令.

 
  1. <#macro addCalc p1 p2=10>

  2. <#if p2=0 && p1=0>

  3. <return>

  4. </#if>

  5. 输出结果为:${p1+p2}

  6. </#macro>

  7. <@addCalc p1=100 p2=200/>

  8. <@addCalc p1=10/>

macro包含nested的宏

 
  1. <#macro myuser name>

  2. 您的姓名是:${name}<br/>

  3. <#nested name?length>

  4. </#macro>

  5. <@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 : 设置格式化输出日期时所使用的时区
 

 
  1. <#--setting设置-->

  2. <#setting locale="zh_CN"/>

  3. <#setting number_format="number"/>

  4. <#setting number_format="currency"/>

  5. <#setting number_format="percent"/>

  6. <#setting date_format="yyyy-MM-dd"/>

  7. <#setting time_format="HH:mm:ss"/>

  8. <#setting datetime_format="yyyy-MM-dd HH:mm:ss"/>

  9. <#setting time_zone="zzzz">

  10.  
  11. <#--string函数格式化-->

  12. <#assign answer=42/>

  13. ${answer}

  14. ${answer?string}

  15. ${answer?string.number}

  16. ${answer?string.currency}

  17. ${answer?string.percent}

  18. <#--EEEE表示星期,MMMM中文月份,yy年份后二位,a(上、中、下午),zzzz时区-->

  19. ${time?string("yyyy-MM-dd HH:mm:ss zzzz")}

  20. ${time?string("EEE,MMM d,yy")}

  21. ${time?string("EEEE,MMMM dd,yyyy,hh:mm:ss a '('zzz')'")}

Java代码读取ftl模板,输出页面

 
  1. public class FreeMarkerUtil {

  2. @SuppressWarnings("deprecation")

  3. public Template getTemplate(String name){

  4. Template temp = null;

  5. // 通过Freemarker的Configuration读取相应的FTL

  6. Configuration cfg = new Configuration();

  7. // 设定去哪里读取相应的ftl模板 ,src/template/

  8. cfg.setClassForTemplateLoading(this.getClass(), "/template");

  9. try {

  10. // 在模板文件目录中寻找名称为name的模板文件

  11. temp = cfg.getTemplate(name);

  12. } catch (IOException e) {

  13. e.printStackTrace();

  14. }

  15. return temp;

  16. }

  17. /**

  18. * 控制台输出文件内容

  19. * @param name

  20. * @param rootMap

  21. */

  22. public void print(String name,Map<String,Object> rootMap){

  23. // 通过Template类可以将模板文件输出到相应的文件

  24. Template temp = this.getTemplate(name);

  25. try {

  26. temp.process(rootMap, new PrintWriter(System.out));

  27. } catch (TemplateException | IOException e) {

  28. e.printStackTrace();

  29. }

  30. }

  31. /**

  32. * 将替换后的模板内容输出到文件

  33. * @param name

  34. * @param rootMap

  35. * @param outFile

  36. */

  37. public void fprint(String name,Map<String,Object> rootMap,String outFile){

  38. File file = null;

  39. try {

  40. //获取项目目录

  41. file = new DefaultResourceLoader().getResource("").getFile();

  42. while(true){

  43. String fileName = file.getName();

  44. file = file.getParentFile();

  45. if("target".equals(fileName)||"src".equals(fileName)){

  46. break;

  47. }

  48. }

  49. //获取模板生成文件位置

  50. } catch (IOException e1) {

  51. e1.printStackTrace();

  52. }

  53. String viewName = file+"/src/main/webapp/";

  54. FileWriter out = null;

  55. try {

  56. out = new FileWriter(new File(viewName+outFile));

  57. Template template = this.getTemplate(name);

  58. template.process(rootMap, out);

  59. } catch (IOException | TemplateException e) {

  60. e.printStackTrace();

  61. }finally{

  62. if(out != null){

  63. try {

  64. out.close();

  65. } catch (IOException e) {

  66. e.printStackTrace();

  67. }

  68. }

  69. }

  70. }

  71. public static void main(String[] args) {

  72. Map<String,Object> rootMap = new HashMap<>();

  73. FreeMarkerUtil freeMarkerUtil = new FreeMarkerUtil();

  74. rootMap.put("time",new Date());

  75. //freeMarkerUtil.print("inc.ftl", rootMap);

  76. freeMarkerUtil.fprint("inc.ftl", rootMap, "01.html");

  77. }

  78. }

与springmvc整合

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

  2. <beans xmlns="http://www.springframework.org/schema/beans"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  4. xmlns:context="http://www.springframework.org/schema/context"

  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

  6. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

  7.  
  8. <context:component-scan base-package="com.ftl.controller"></context:component-scan>

  9.  
  10. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

  11. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

  12.  
  13. <!-- 配置Freemarker属性文件路径 -->

  14. <bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">

  15. <property name="location" value="classpath:freemarker.properties" />

  16. </bean>

  17.  
  18. <!-- 配置freeMarker模板加载地址 -->

  19. <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">

  20. <!-- 视图解析器在/tpl/路径下扫描视图文件 -->

  21. <property name="templateLoaderPath" value="/tpl/" />

  22. <property name="freemarkerVariables">

  23. <map>

  24. <entry key="xml_escape" value-ref="fmXmlEscape" />

  25. </map>

  26. </property>

  27. <property name="freemarkerSettings">

  28. <props>

  29. <!-- 模板编码格式 -->

  30. <prop key="default_encoding">UTF-8</prop>

  31. <!-- 本地化设置 -->

  32. <prop key="locale">UTF-8</prop>

  33. <!-- url转义编码 -->

  34. <prop key="url_escaping_charset">UTF-8</prop>

  35. </props>

  36. </property>

  37. </bean>

  38. <bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" />

  39.  
  40. <!-- 配置freeMarker视图解析器 -->

  41. <bean id="freemakerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">

  42. <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />

  43. <!-- 扫描路径內所有以ftl結尾的文件 -->

  44. <property name="viewNames">

  45. <array>

  46. <value>*.ftl</value>

  47. </array>

  48. </property>

  49. <property name="contentType" value="text/html; charset=UTF-8" />

  50. <property name="exposeRequestAttributes" value="true" />

  51. <property name="exposeSessionAttributes" value="true" />

  52. <property name="exposeSpringMacroHelpers" value="true" />

  53. <property name="requestContextAttribute" value="request" />

  54. <!-- 给视图解析器配置优先級,你可以给之前jsp视图解析器的值配为2 -->

  55. <property name="order" value="1" />

  56. </bean>

  57. </beans>