`
zengjinliang
  • 浏览: 307627 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

FreeMarker一篇通1

阅读更多

大家看文章标题就应该知道,我想用一篇文章,把大家从对freemaker的陌生直接带入到比较深入的境界,所以不想说一些基础性的东西,如果大家不习惯我的表达方法,大可通过google去找习惯于自己阅读方式的相关文章。

我用过velocity,最近才用freemaker,才知道我以前的选择是错了,因为velocity不支持过程的调用,所以我为velocity增加了很多的东西,写了很多代码,而且脚本也累赘得要命。freemaker首先吸引我的是它强大的过程调用和递归处理能力,其次则是xml风格的语法结构有着明显的边界,不象velocity要注意段落之间要留空格。所以我建议大家直接使用Freemaker,虽然freemaker没有.net版本,我想不嵌入程序中使用的话,freemaker是绝对的首选。(题外话,谁有兴趣移植一个NFreeMaker?)

在使用之前我们先要设置运行环境,在使用Freemaker的时候,我们需要下载相关的程序:
freemaker: http://freemarker.sourceforge.net/
fmpp: http://fmpp.sourceforge.net/

其中fmpp是一个freemaker的辅助工具,有了它,我们可以实现更多的功能。以下例子必须fmpp辅助。

这里我们首先提出问题。大家看如下的一个xml文件,虽然freemaker的能力不仅在于处理xml文件,但是用xml作为例子更直观一些:

 

 

<!---->xml version='1.0' encoding="gb2312" ?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:DruleForm-Lite.xsd">
        
<type name="Type1" >
            
<labels>
                
<label lang="zh-CN" value="投保单"/>
            
labels>
            
<field name="Field11" type="Float" lbound="1" ubound="1" >
                
<labels>
                    
<label lang="zh-CN" value="投保单ID"/>
                
labels>
            
field>
            
<field name="Field12" type="String" lbound="1" ubound="*"/>
            
<field name="Field13" type="Integer" lbound="1" ubound="*"/>
            
<field name="Field14" type="Type2" lbound="1" ubound="*">
                
<type name="Type2">
                    
<field name="Field21" type="String" lbound="1" ubound="*"/>
                    
<field name="Field22" type="Integer" lbound="1" ubound="*"/>    
                
type>
            
field>
            
<field name="Field15" type="InsuranceProduct" lbound="1" ubound="*"/>
        
<type>
        
<type name="Type3">
            
<field name="Field31" type="Type1" lbound="1" ubound="*" />
        
type>
    
types>

 

 [代码1]
我们的任务是把这个文件转化为相应的C#代码。大家先看转换模板的代码:

 

 1<#ftl ns_prefixes={"ns": "urn:DruleForm-Lite.xsd"}> 
 2<#-- 定义xml namespace,以便在以下代码中使用,注意,ftl指令必须使用单独的行 -->
 3<@pp.setOutputEncoding encoding="gb2312" /> <#-- 使用fmpp提供的函数来设置输出编码 -->
 4
 5<#recurse doc> <#-- 根入口,代码1部分的xml存放在变量doc中,doc变量的填充由fmpp根据config.fmpp中的配置进行 -->
 6
 7<#macro "ns:types"> <#-- xslt风格的匹配处理入口 -->
 8<#recurse> <#-- 直接进行types节点内的匹配 -->
 9#macro>
10
11<#macro "ns:type"> <#-- 匹配type节点 -->
12 class ${.node.@name} <#-- 其中.node是保留字,表示当前节点,引用的@name是xslt风格 -->
13 {
14  <#recurse> <#-- 继续匹配 -->
15 }
16#macro>
17
18<#macro "ns:field">
19  public ${.node.@type} ${.node.@name};
20#macro>
21
22<#macro @element> <#-- 所有没有定义匹配的节点到这里处理 -->
23#macro>
24
25

 

[代码2]

我们使用的配置文件设置如下:

 

sourceRoot: src
outputRoot: out
logFile: log.fmpp
modes: 
[
 copy(common/**/*.*, resource/*.*)
    execute(*.ftl)
 ignore(templates/*.*
, .project, **/*.xml, xml/*.*, *.js)
]
removeExtensions: ftl
sourceEncoding: gb2312
data: {
 doc: xml(freemaker.xml)
}

 

[代码3]

然后我们在dos模式下运行指令:
E:\work\blogs\freemaker>f:\download\freemaker\fmpp\bin\fmpp

最后的输出结果是这样的,存放在文件out\freemaker.中:

 

 

    class Type1 
    
{
        
public Float Field11;
        
public String Field12;
        
public Integer Field13;
        
public Type2 Field14;
        
public Float Field15;
    }

 
    
class Type3 
    
{
        
public Type1 Field31;
    }

 

[代码4]

先来解释一下freemaker的基本语法了,
<# ... > 中存放所有freemaker的内容,之外的内容全部原样输出。
<@ ... /> 是函数调用
两个定界符内的内容中,第一个符号表示指令或者函数名,其后的跟随参数。freemaker提供的控制包括如下:
<#if condition><#elseif condition><#else> 条件判断
<#list hash_or_seq as var> 遍历hash表或者collection(freemaker称作sequence)的成员
<#macro name param1 param2 ... ><#nested param> 宏,无返回参数
<#function name param1 param2><#return val>函数,有返回参数
var?member_function(...) 用函数对var进行转换,freemaker称为build-ins。实际内部实现类似member_function(var, ...)
stringA[M .. N] 取子字符串,类似substring(stringA, M, N)
{key:value, key2:value2 ...} 直接定义一个hash表
[item0, item1, item2 ...] 直接定义一个序列
hash0[key0] 存取hash表中key对应的元素
seq0[5] 存取序列指定下标的元素
<@function1 param0 param1 ... /> 调用函数function1
<@macro0 param0 param1 ; nest_param0 nest_param1 ...> nest_body </@macro> 调用宏,并处理宏的嵌套
<#assign var = value > 定义变量并初始化
<#local var = value> 在 macro 或者 function 中定义局部变量并初始化
<#global var = value > 定义全局变量并初始化
${var} 输出并替换为表达式的值
<#visit xmlnode> 调用macro匹配xmlnode本身及其子节点
<#recurse xmlnode> 调用macro匹配xmlnode的子节点

[表1]


大家仔细对比xml文件,发现少了什么吗?对了,少了一个Type2定义,我们把代码2中的ns:type匹配(第11行)修改一下:

 

<#macro "ns:field">
  public ${.node.@type} ${.node.@name};
  
<#recurse > <#-- 深入处理子节点 -->
#macro>

 

[代码5]

结果输出文件中的内容就变为如下:

 

 

    class Type1 
    
{
        
public Float Field11;
        
public String Field12;
        
public Integer Field13;
        
public Type2 Field14;
        
class Type2 
        
{
            
public String Field21;
            
public Integer Field22;
        }

        
public Float Field15;
    }

 
    
class Type3 
    
{
        
public Type1 Field31;
    }

 

[代码6]

如果各位有意向把Type2提到跟Type1和Type3同一级别的位置,那么我们要继续修改代码了。把代码2的 <#recurse doc>行(第5行)修改成如下:

 

<#assign inner_types=pp.newWritableHash()> <#-- 调用fmpp功能函数,生成一个可写的hash -->
<#recurse doc> <#-- 根入口,代码1部分的xml存放在变量doc中,doc变量的填充由fmpp根据config.fmpp中的配置进行 -->
<#if inner_types?size gt 0 > <#-- 如果存放有类型 -->
 
<#list inner_types?values as node> <#-- 遍历哈西表的值 -->
  
<#visit node> <#-- 激活相应的macro处理,类似于xslt的apply-template。大家把visit改成recurse看一下不同的效果 -->
 
#list>
#if>

 

[代码7]

同时把macro ns:field(第18行)修改成如下:

 

<#macro "ns:field">
  public ${.node.@type} ${.node.@name};
  
<#if .node["ns:type"]?has_content > <#-- 如果当前节点下存在type节点 -->
   
<#local = .node["ns:type"] >
   
<@pp.set hash=inner_types key="${t.@name}" value=t /> <#-- 哈西表中增加内容,key为嵌套类型的name属性,value为该类型节点 -->
  
#if>
#macro>

 

分享到:
评论

相关推荐

    freemarker实现一行两列算法

    ### Freemarker实现一行两列布局算法 在Web开发中,数据展示经常需要按照特定的格式进行排列,例如常见的列表项按行对齐显示等。Freemarker作为一种强大的模板引擎,可以方便地处理这类布局需求。本文将详细介绍...

    freemarker 自定义freeMarker标签

    1. 创建自定义指令类:你需要创建一个继承自`freemarker.template.TemplateDirectiveModel`的Java类。这个类将定义你的自定义标签的行为,包括如何处理输入参数,如何处理模板模型数据,以及如何生成输出。 2. 注册...

    一篇很全面的freemarker教程

    一篇很全面的freemarker教程reeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:格式部分,不会输出 3,插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代输出 4,FTL指令:...

    freemarker Demo 适用于freemarker初学

    1. **Freemarker简介** Freemarker是一个基于模板的开源模板语言,它与Java代码分离,使得开发者可以专注于业务逻辑,而设计师则可以专注于页面设计。它不依赖于任何特定的Web框架,可以在各种Java应用中使用。 2....

    freemarker

    一篇freemarker很不错的文章 reeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:格式部分,不会输出 3,插值:即${...}或#{...}格式的部分,将使用...

    eclipse的freemarker插件

    1. **代码格式化**:允许用户自定义代码格式化规则,如缩进方式(空格或制表符)、缩进宽度、换行处理等,自动整理Freemarker模板代码,使其符合编码规范。 2. **语法高亮**:提供Freemarker关键词和语法的色彩突出...

    freemarker-2.3.23jar

    `freemarker-2.3.23.jar`是Freemarker库的一个版本,发布于2.3.23,这个版本可能包含了对早期版本的一些改进、新功能或bug修复。 Freemarker的核心概念是模板语言,它是一种声明式的编程方式,允许开发者编写不包含...

    FreeMarker手册-Freemarker 2.3.18

    FreeMarker 2.3.18是该引擎的一个版本,它提供了一系列的更新和改进,以提高性能和易用性。 1. **模板语言基础** FreeMarker的模板语言是一种声明式的编程方式,它允许开发者通过简单的标记语法来控制输出。这些...

    freemarker-2.3.28.jar

    1. **模板语言FTL**: Freemarker使用的模板语言叫做FreeMarker Template Language (FTL),它是一种声明式的、非过程式的语言。FTL文件包含了一系列的指令和表达式,用于生成最终输出。例如,`&lt;#if&gt;`、`&lt;#foreach&gt;`、...

    FreeMarker中文版文档1

    FreeMarker 是一个强大的模板引擎,主要用于生成动态内容,如网页、邮件、报告等。它与Spring框架集成紧密,常作为视图层的技术选择。在软件/插件领域,FreeMarker因其简洁的语法和高效的性能而受到青睐。 1.1 简介...

    FreeMarker

    1. **变量与表达式**:在FreeMarker模板中, `${variable}` 用于表示变量,它会从数据模型中查找对应的值并输出。表达式支持算术运算、比较运算和逻辑运算,例如 `${a + b}`、`${c &gt; d}` 和 `${e && f}`。 2. **...

    freemarker.jar

    camel-freemarker-1.6.4.jar, camel-freemarker-2.8.1.jar, com.springsource.freemarker-2.3.15.jar, com.springsource.freemarker-sources-2.3.15.jar, freemarker-1.4.1.jar, freemarker-2-3-18.jar, freemarker-...

    FreeMarker2.3.23官方中文文档

    1. **变量和表达式**:在FreeMarker模板中,`${}`内的内容是表达式,用于获取Java对象的属性或执行简单的运算。例如`${user.name}`将输出用户对象的name属性。 2. **指令**:FreeMarker提供了一系列的内置指令,如`...

    struts1+spring+hibernate+freemarker一个小例子

    在这个“struts1+spring+hibernate+freemarker一个小例子”中,我们将探讨这四个组件如何协同工作,以及它们各自的核心功能。 首先,Struts1是MVC(模型-视图-控制器)设计模式的一个实现,主要用于处理HTTP请求和...

    FreeMarker的一个DEMO

    1. **FreeMarker的基本概念** - **模板**: FreeMarker的核心是模板文件,通常以`.ftl`为扩展名。模板包含HTML代码以及控制结构(如条件语句和循环),以及用于插入动态数据的占位符。 - **数据模型**: 这是传递给...

    FreeMarker通用的分页

    FreeMarker提供了一种灵活且强大的方式来处理动态内容,尤其适用于Web开发中的视图层。在FreeMarker中实现通用的分页功能是提高Web应用程序性能和用户体验的重要一环。 ### FreeMarker通用分页知识点解析 #### 1. ...

    freemarker解析成pdf

    1. **创建模板**:在Freemarker中,我们需要创建一个`.ftl`(Freemarker Template Language)文件,其中包含静态文本和动态占位符。动态占位符由${}或#{}包裹,用于插入数据模型中的值。例如,`${title}&lt;/h1&gt;`会将...

    FreeMarker教程篇

    Freemaker是一个强大的模板引擎,FreeMarker教程适合初学者学习

Global site tag (gtag.js) - Google Analytics