freemarker模板引擎

一. 模板引擎技术

Freemarker 是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写,具有以下特点:

1Freemarker 适合被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序。

2)虽然Freemarker 具有一些编程的能力,但通常由Java程序准备要显示的数据,由Freemarker 生成页面,通过模板显示准备的数据 。

3Freemarker 不是一个Web应用框架,而适合作为Web应用框架一个组件。

4Freemarker 与容器无关,因为它并不知道HTTPServlet

5Freemarker 更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库。

6Freemarker 是免费的 。

二 .freemarker简介

    在互联网软件内容网站中 一般首页的访问量大,为了提供首页的访问效率,一般 首页的内容以及其中的新闻等信息都可以实现html静态化 浏览器访问时 设置浏览器的缓存策略和生成静态页面的周期一致 可以使访问效率大大提升 同时配合cdn处理图片 js css等资源 可以在首页访问时 理论完全脱离数据库  降低应用压力

  原理图:

   

实际应用案例

  比如 新闻门户网站  后台添加新闻时  通过新闻数据+预定义的模板ftl 生成静态的html  新闻数据插入数据库 绑定该html新闻保存的html位置 如果该新闻被推送到首页 

生成首页静态html时  将该新闻的超链接指向 该文章的静态html

下图访问服务(nginx集群+cdn缓存+后台应用服务器  MQ表示队列)



三.标准的FTL标记指令

1) if, else, elseif

2) switch, case, default, break

3) list, break

4) include

5) Import

6) assign

7) macro, nested, return

四.freeemarker模板语法

1.<#----------------------字符串的转义处理  -->  
${"我的名字是\"zs\""}  
${r"我的名字是:${name}"}<#--字符串的${}添加了r表示是纯文本 直接输出不解析-->  

freemarker的模板 ftl为后缀 语法类似于jsp的标签

2.类(if,list条件循环实例)

public class TestFreemarker {

public static void main(String[]args) throws IOException, TemplateException {

Configurationcfg = new Configuration();

//配置ftl查找目录

cfg.setDirectoryForTemplateLoading(new File("templates"));

//设置数据的抓取模式

cfg.setObjectWrapper(new DefaultObjectWrapper());

Map latest =new HashMap();

//构建数据

latest.put("url","products/greenmouse.html");

latest.put("name","green mouse");

Map root =new HashMap();

root.put("latestProduct",latest);

root.put("user","Big Joe");

root.put("sex","1");

String [] str = new String[]{"1","2","3","4","5"};

root.put("arr",str);

List list =new ArrayList<>();

User user = new User();

user.setId("1");

user.setName("wangwu");

list.add(user);

User user1 = new User();

user1.setId("2");

user1.setName("xiaohong");

list.add(user1);

root.put("userList",list);

//实例化模板对象

Template temp = cfg.getTemplate("helloworld.ftl");

FileOutputStreamfos = new FileOutputStream("F:\\html\\hello.html");

//生成html  输出到目标

Writer out = new OutputStreamWriter(fos);

temp.process(root,out);

out.flush();

}

}

<#------------helloworld.ftl模板

 

<html>

<head>

  <title>Welcome!</title>

</head>

<body>

  <h1>Welcome${user?default('')}!</h1>

  <p>Our latest product:

  <ahref="${latestProduct.url}">${latestProduct.name}</a>!

  

  我的性别是:

  <#--if语句判断   键等于值,然后输出-->

  <#if sex='2'>

   男

  <#else>

   女

  </#if>

  <br/>

<#--------------------- 循环语句   

  for循环   

foreach  

临时变量 _index表示当前的下标  

临时变量 _has_next表示是否还有下一个值  

#break表示终止循环  

--------->  

<#list 1..9 as i>  

  ${i}  

</#list>  

  <#-------list循环标记 数组或者集合as 临时变量

  临时变量_index 获取当前的索引从0开始

  break 标记用于突出循环

  list循环  先把集合放在前面 ,然后再 as 变量名 最后输出-------->

输出结果:

  <#listarr astemp>

   <#if temp_index=2>

   <#break>

   </#if>

   <#if (temp_index+1)%2==0>

  <font color=green>${temp}---${temp_index+1}</font><br/>

   <#else>

  <font color=yellow>${temp}---${temp_index+1}</font><br/>

   </#if>

  </#list>

 输出集合list

 <#list userList as userTmp>

  ${userTmp.id}---${userTmp.name}

 </#list>

 

---------->

3.类(Include,assign,import包含的实例)

public class TestIncludeFreemarker {

public static void main(String[]args) throws IOException, TemplateException {

Configurationcfg = new Configuration();

//配置ftl查找目录

cfg.setDirectoryForTemplateLoading(new File("templates"));

//设置数据的抓取模式

cfg.setObjectWrapper(new DefaultObjectWrapper());

Map root =new HashMap();

//实例化模板对象

Template temp = cfg.getTemplate("testinclude.ftl");

//生成html  输出到目标

Writer out = new OutputStreamWriter(System.out);

temp.process(root,out);

out.flush();

}

}

<#--定义变量-->  

<#assign id=1 name='zs' sex='boy' ifSuc=true>  

<#----------include.ftl模板 include包含会覆盖当前ftl中相同名字的变量 --------->

<#include"include1.ftl">

<#include"include.ftl">

${age}

<#----------------------import包含模板 使用一个别名来控制包含文件中变量的作用于     访问时使用 inc.变量名不会覆盖当前ftl变量--->    

<#import"include1.ftl"as c>

<#import"include.ftl"as c1>

${c.age}--${c1.age}

 

4.类(macro宏实例)

public class TestMacroFreemarker {

public static void main(String[]args) throws TemplateException, IOException {

Configurationcfg = new Configuration();

//配置ftl查找目录

cfg.setDirectoryForTemplateLoading(new File("templates"));

//设置数据的抓取模式

cfg.setObjectWrapper(new DefaultObjectWrapper());

Map root =new HashMap();

List list =new ArrayList<>();

User user = new User();

user.setId("1");

user.setName("wangwu");

list.add(user);

User user1 = new User();

user1.setId("2");

user1.setName("xiaohong");

list.add(user1);

root.put("userList",list);

//实例化模板对象

Template temp = cfg.getTemplate("macro.ftl");

//生成html  输出到目标

Writer out = new OutputStreamWriter(System.out);

temp.process(root,out);

out.flush();

}

}

<#----------------macro宏

将特殊的代码封装起来,用是直接调用就可以了(只会定义,不会执行,只有调用时才会执行

类似于java中的方法 定义不会执行 调用才会执行 定义参数可以给默认值  

比如 addCalc p1 p2=10  如果调用不传入p2 默认就是10  ------>  

<#macro mymacro p1 p2=10>

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

<#return>

</#if>

结果是:${p1*p2}

</#macro>

<@mymacro p1=100 p2=2/>

<@mymacro p1=10 p2=10/>

<br/>

<#--------macro中使用嵌套 #nested将 调用宏 body内容嵌套进入------->  

<#macro myuser name>  

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

  <#nested name?length>  

</#macro>  

<@myuser name='zs';len>名字长度:${len}</@myuser>  

<br/>  

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

<#assign str=" welcome how are you " >

${str?length}

---${str?trim}---

${str?upper_case}

${str?lower_case}

${userList?size}

<#if ab?exists><#--判断变量是否存在-->

${ab}

</#if>

---------->

5.类(数组实例)

public class TestMapFreemarker {

public static void main(String[]args) throws IOException, TemplateException {

Configuration cfg = new Configuration();

//配置ftl查找目录

cfg.setDirectoryForTemplateLoading( new File("templates"));

//设置数据的抓取模式

cfg.setObjectWrapper(new DefaultObjectWrapper());

Map latest = new HashMap();

//构建数据

latest.put("id1","5");

latest.put("id2","2");

latest.put("id3","3");

Map root = new HashMap();

root.put("myid",latest);

//实例化模板对象

Template temp = cfg.getTemplate("map.ftl");

//生成html  输出到目标

Writer out = new OutputStreamWriter(System.out);

temp.process(root,out);

out.flush();

}

}

<--------数组map.ftl模板

<#list myid?values astmp>

${tmp}

</#list>

<#--定义数组-->

<#assign arr=['a','b','v']>

<#list arr as tmp>

${tmp}

</#list>

-------->


.freeemarker在javase和javaee使用

 1.javase环境下 可以将模板+数据的结果生成html 输出到指定位置

maven中添加freemarker依赖

<dependency>  
<groupId>org.freemarker</groupId>  
<artifactId>freemarker</artifactId>  
  <version>2.3.26-incubating</version>  
</dependency> 

添加测试类 main方法中添加:

Configurationcfg = new Configuration(Configuration.VERSION_2_3_26);  
cfg.setDirectoryForTemplateLoading(new File("src/main/resources"));  
cfg.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_26));  
Map root = new HashMap();  
root.put("user", "Big Joe");  
Template temp = cfg.getTemplate("test.ftl");  
Writer out = new OutputStreamWriter(System.out);  
temp.process(root, out);  
out.flush(); 

src/main/resources仙剑test.ftl

<html>  
<head>  
<title>Welcome!</title>  
</head>  
<body>  
<h1>Welcome ${user?default('')}!</h1>  

</body>  

运行main方法发现输出了 对应的网页

 2.javaee环境下 使用freemarkerservlet寻找ftl文件并输出 

javaee下部署访问页面的结构图 (MVC)


freemarker也支持上述模型

maven 添加依赖包  同上

添加一个servlet   映射路径 /t  web.xml添加:

<servlet>  
    <description></description>  
    <display-name>TestSErvlet</display-name>  
    <servlet-name>TestSErvlet</servlet-name>  
    <servlet-class>webtest.TestSErvlet</servlet-class>  
 </servlet>  
<servlet-mapping>  
    <servlet-name>TestSErvlet</servlet-name>  
    <url-pattern>/t</url-pattern>  
</servlet-mapping>

配置freemarkerservlet web.xml添加 

<servlet>  
    <servlet-name>freemarker</servlet-name>  
    <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>  
      <init-param>      
        <param-name>TemplatePath</param-name>      
        <param-value>/</param-value>    <!--表示从上下文路径根目录寻找模板文件-->  
    </init-param>     
    <init-param>      
        <param-name>NoCache</param-name>      
        <param-value>true</param-value> <!--不使用缓存-->     
     </init-param>      
     <init-param>    
          <param-name>ContentType</param-name>    
          <param-value>text/html;charset=UTF-8</param-value>  <!--响应的数据类型-->  
     </init-param>    
     <init-param>    
         <param-name>template_update_delay</param-name>    
         <param-value>0</param-value>    
     </init-param>    
     <init-param>    
         <param-name>default_encoding</param-name>    
         <param-value>UTF-8</param-value>    
     </init-param>    
     <init-param>      
        <param-name>number_format</param-name>      
        <param-value>0.##########</param-value>      
     </init-param>      
     <load-on-startup>1</load-on-startup>  
</servlet>  
<servlet-mapping>  
    <servlet-name>freemarker</servlet-name>  
    <url-pattern>*.ftl</url-pattern><!--所有ftl都经过该servlet-->  
</servlet-mapping>  


maven项目 /src/main/java/webapps随便添加一个模板 test.ftl 

<html>  
  <head>  
    <title>Welcome!</title>  
  </head>  
  <body>  
    <h1>Welcome ${user?default('')}!</h1>  
    <p>Our latest product:  
    <a href="${latestProduct.url?default('')}">${latestProduct.name?default('')}</a>  
    ${user}  
     <#if sex='0'>  
      body  
     </#if>  
        <#assign id=1><br/>  
     ${id}      
     <#macro users name>  
           这是用户:${name}  
     </#macro>  
    
     <@users name='zs'></@users>  
     <@users name='ls'></@users>  
  </body>  
</html>    

3.request设置值时 添加

request.setAttribute("myAdd", new MyMethod()); 

六.freemarker插件安装

freemarkder插件的下载地址为 :https://sourceforge.net/projects/freemarker-ide/files/freemarker-ide/

 下载freemarker-ide-0.9.14.zip (909.6 kB)

  解压后目录 植入 eclipse/plugsin目录即可 



:模板中的变量的使用范围及命名空间

变更的使用范围:

plain(全局)变量:可以在模板的任何地方访问,包括使用include指令插入的模板,使用assign指令创建和替换

局部变量:在macro中有效,使用local指令创建和替换

循环变量:只能存在于指令的嵌套内容,由指令(如list)自动创建;宏的参数是局部变量,而不是循环变量

局部变量隐藏(而不是覆盖)同名的plain变量;

循环变量隐藏同名的局部变量和plain变量,下

面是一个例子 :

<#assign x = "plain"> 1. ${x}  
<@test/> 6. ${x}  
<#list ["loop"] as x>
    7. ${x}  
<#assign x = "plain2"> 
    8. ${x} 
</#list> 9. ${x}  
<#macro test>
  2. ${x}    <#local x = "local">
  3. ${x} 
  <#list ["loop"] as x>
    4. ${x} 
  </#list>
  5. ${x} 
</#macro> 

模板中的变量会隐藏(而不是覆盖)数据模型中同名变量,如果需要访问数据模型中的同名变量,使用特殊变量global,下面的例子假设数据模型中的user的值是
Big Joe:
<#assign user = "Joe Hider">
${user}              <#-- prints: Joe Hider -->
${.globals.user} <#-- prints: Big Joe -->   

命名空间技术:
通常情况,只使用一个命名空间,称为主命名空间(main namespace),但你是不会意识到这些的;为了创建可重用的macro必须使用多命名空间,为了防止同

名冲突,列如:

首先创建一个库(假设保存在lib/my_test.ftl中):
<#macro copyright date>
<p>Copyright (C) ${date} Julia Smith. All rights reserved.
<br>Email: ${mail}</p>
</#macro>
<#assign mail = "jsmith@acme.com"> 
使用import指令导入库到模板中,Freemarker会为导入的库创建新的命名空间,并可以通过import指令中指定的hash(散列)变量访问库
中的变量:
<#import "/lib/my_test.ftl" as my>
<#assign mail="fred@acme.com">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}  


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值