Freemaker_入门+深入+开发指南+学习笔记

Freemaker 入门+深入+开发指南+学习笔记

freemaker的基本语法

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 调用宏,并处理宏的嵌套
<#assign var = value > 定义变量并初始化
<#local var = value> 在 macro 或者 function 中定义局部变量并初始化
<#global var = value > 定义全局变量并初始化
${var} 输出并替换为表达式的值
<#visit xmlnode> 调用macro匹配xmlnode本身及其子节点
<#recurse xmlnode> 调用macro匹配xmlnode的子节点

 

FreeMaker一篇通[【转】

FreeMaker一篇通[【转】

2007-08-09 19:38

FreeMaker一篇通

前言

Freemaker是一个强大的模板引擎,相比velocity而言,其强大的过程调用、递归和闭包回调功能让freemaker可以完成几乎所有我们所想的功能。从个人看法而言,freemaker完全有能力作为MDA的代码辅助生成工具。
本文试图越过传统的概念性介绍,通过一组例子直接把读者带入到Freemaker应用的较高层阶。

正文

大家看文章标题就应该知道,我想用一篇文章,把大家从对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作为例子更直观一些:


http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:DruleForm-Lite.xsd">
        
            
                

            
                
                    

            

            
            
            
                
                    
                         
                

            

            
        
        
            
        

    

[代码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
10
11<#macro "ns:type"> <#-- 匹配type节点 -->
12 class ${.node.@name} <#-- 其中.node是保留字,表示当前节点,引用的@name是xslt风格 -->
13 {
14   <#recurse> <#-- 继续匹配 -->
15 }
16
17
18<#macro "ns:field">
19   public ${.node.@type}${.node.@name};
20
21
22<#macro @element> <#-- 所有没有定义匹配的节点到这里处理 -->
23
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 调用宏,并处理宏的嵌套
<#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 > <#-- 深入处理子节点 -->


[代码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看一下不同的效果 -->


[代码7]

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

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

[代码8]

运行得到输出文件类似这样:

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

     class Type3
     {
         public Type1 Field31;
     }

     class Type2
     {
         public String Field21;
         public Integer Field22;
     }

[代码9]

大家比较一下,看看我们修改的地方出现了哪些效果?然后记得大家要做另外2件事情,
1。把第一行修改成为<#ftl ns_prefixes={"D": "urn:DruleForm-Lite.xsd"}> ,然后把所有的 <#macro "ns:type"> 修改成<#macro type>,把所有的.node["ns:type"]修改成 .node.type,看看能不能运行?是不是觉得简单方便些了?记住,第一行的那个D表示是default namespace的意思哦。
2。在第二行插入<#compress>,在最后一行添加。再运行一下看看结果有什么不同?

一个例子下来,大家基本对freemaker有了一些感觉了,为了纠正大家认为freemaker就是一个xml处理工具的误解,我们再来做一个简单的实验。这次我们要做的是一个正常的编程题目,做一个100以内的Fibonacci数列的程序。程序如下:

迭代次数:
<#list 1 .. 10 as n>
${n} = ${fibo(n)}

<#compress>
<#function fibo n>
<#if n lte 1>
   <#return 1>
<#elseif n = 2>
   <#return 1>
<#else>
   <#return fibo(n-1) + fibo(n-2)>



[代码10]

这个例子里边有一些问题需要注意,大家看我的 #if n lte 1 这一行,为什么我这么写?因为常规的大于小于号和xml的节点有冲突,为了避免问题,所以用 gt(>) gte(>=) lt(<) lte(<=) 来代表。

另外,复杂的字符串处理如何来做?就留作家庭作业吧,大家记得取substr的方法是 str[first .. last] 就可以了。如下的例子可能会给你一点提示:

<#assign str = "hello!$world!">
<#assign mid = (str?length + 1)/2-1 >
<#list mid .. 0 as cnt>
${str[(mid - cnt) .. (mid + cnt)]?left_pad(mid*2)}

[代码11]

最后,说一下非常有用的macro的nested指令,没有它,也许freemaker会失去大部分的魅力。我个人认为这也是freemaker全面超越velocity的地方。大家先看一下代码:

<#assign msg = "hello">
<@macro0 ; index >
${msg} ${index}

<#macro macro0>
<#list 0 .. 10 as number>
   <#nested number>


[代码12]

这段代码的作用就是一个闭包(closure)。我们用java的匿名类实现相同的功能就是这样:

interface ICallback
{
public void call(int index);
}

void Main()
{
String msg = "hello";
macro0(
   new ICallback()
   {
    public void call(int index)
    {
     System.out.println(msg + index.toString());
    }
   }
);
}

void macro0(ICallback callback)
{
for(int i = 0; i < 10; ++i)
{
   callback.call(i);
}
}

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的子节点


<#if condition >
<#list SequenceVar as variable > repeatThis
<#include "/copyright_footer.html">

一个ftl标记不能放在另外一个ftl标记里面,但是注释标记能够放在ftl标记里面。

系统预定义指令采用<#...>
用户自定义指令采用<@...>

hash片段可以采用:
products[10..19] or products[5..] 的格式。

序列也可以做加法计算:passwords +{"joe":"secret42"}

缺省值: name!"unknown" 或者 (user.name)!"unknown" 或者 name! 或者 (user.name)!

null值检查: name?? or (user.name)??

转义列表:

Escape sequence

Meaning

\"

Quotation mark (u0022)

\'

Apostrophe (a.k.a. apostrophe-quote) (u0027)

\\

Back slash (u005C)

\n

Line feed (u000A)

\r

Carriage return (u000D)

\t

Horizontal tabulation (a.k.a. tab) (u0009)

\b

Backspace (u0008)

\f

Form feed (u000C)

\l

Less-than sign: <

\g

Greater-than sign: >

\a

Ampersand: &

\{

Curly bracket: {

\xCode

Character given with its hexadecimal Unicode code (UCS code)


如果想打印${,则需要将{转义,可以写成"$\{user}",或者可以用生字符(r指令):$(r "${xx}"}

序列构成:<#list ["winter","spring", "summer", "autumn"] asx>${x}

不同的对象可以存放在一个序列里面,比如:[2 + 2,[1, 2, 3, 4], "whatnot"]. 第一个是数字,第二个是序列,第三个是字符串。

可用采用start..end的方式来定义一个数字序列,start可以小于end,同时,end也可以省略。

hash取值支持一下四种模式:book.author.name, book["author"].name, book.author.["name"], book["author"]["name"].

特殊变量是指freemaker引擎本身定义的变量。访问时,以.variable_name的语法访问。

变量表达式支持嵌套模式,比如:${"Hello${user}!"}。

变量表达式在指令中的使用情况:
变量表达式可以在指令中,用“”的方式存在,不如:<#include"/footer/${company}.html">.
但是不允许下面的方式存在: <#if ${isBig}>Wow!, 正确写法是:<#ifisBig>Wow!.
而且 <#if"${isBig}">Wow!写法也不正确,因为"${isBig}"返回的是字符串,不是boolean类型。

字符串中取字符或字符串采用以下语法:${user[0]},${user[0..2]}${user[4..]},${user?string(4)}

序列操作:
   加法:<#list ["Joe", "Fred"] + ["Julia","Kate"] as user> 但要注意串联之后的读取速度变慢。
   子序列:seq[1..4]

序列和hash的串联都只能用于两个相加,不能有多个相加的模式,hash相加,如果两个相加的hash存在相同的key,则后面会覆盖前面的。

在使用>=或者>时,需要注意一些问题,因为freemaker会将>解释成标记的关闭符,为了解决这个问题,需要在表达式加上括号,比如: <#if (x > y)>. 或者使用 > and <符号来代替。

无值变量(包括无该变量,null,返回void,无属性等):unsafe_expr!default_expr or unsafe_expr! or (unsafe_expr)!default_expr or (unsafe_expr)!
缺省值可以是任何类型,不一定是数字,比如:hits!0 或者 colors!["red","green", "blue"].

如果缺省值忽略,那么将会默认为空串、空序列或者空hash,因为freemarker支持多类型的值。不过要让默认值为0或false,则不能省略缺省值。

非顶层变量的无值处理:
   product.color!"red":只处理product不为空,color为空的缺省值处理,如果product为空,则freemaker会抛出异常。(product.color)!"red":则会处理product为空,color为空,或者没有color属性的无值情况。

无值变量的判断操作:unsafe_expr?? or (unsafe_expr)??

判断变量是否是无值。

普通变量插入方式: ${expression},${3+5);
数字变量插入方式: #{expression} or #{expression; format}:过期。
变量只能用于文本区或者是字符串里面,比如:

Hello${name}!

以及 <#include"/footer/${company}.html">

数字值的插入:根据缺省的number_format输出,以及可以通过setting来达到设置数字格式的目的,也可以通过内置函数string来改变输出格式。

日期类型的格式设置:date_format, time_format 和 datetime_format


定义宏:
   不带参数:<#macro 宏名>...,引用<@宏名 />
   带参数:<#macro宏名 参数...>...,引用<@宏名 参数1=值1.../>,带有参数的宏,调用是参数的值必须和参数的个数相同。当然也可以在宏定义时给参数一些默认值。比如:<#macro greet person color="black">


宏里面的嵌套内容:
<#macro border>
 

    <#nested>
 

 
在宏的定义body中加入<#nested>指令。嵌套的内容可以是任何正确的ftl块。

宏的本地变量在嵌套内容中是不可见的。

宏定义时,<#nest>指令相当于调用定义的内容,而使用宏时,nest body相当于定义。

<#macro repeat count>  <#list 1..count as x>    <#nested x, x/2, x==count<@repeatcount=4 ; c, halfc, last>  ${c}.${halfc}<#iflast> Last! 



定义变量:
   在模板中定义的变量将会隐藏(不是更改)数据模型根下面的同名的变量。

模板中的3种类型变量:
   1:plain variables,能够在模板中的任何地方访问,一个模板include另外一个模板,也可以访问被包含模板的变量。可以通过assign或者macro指令产生或替换变量。
   如果要访问数据模型中的变量,则可以通过.global来访问:
   <#assign user = "JoeHider">
   ${user}         <#-- prints: Joe Hider -->
   ${.globals.user} <#-- prints: Big Joe--> 
   2:Local variables,宏定义body中用local指令创建或者替换。
   3:Loop variables:由list指令产生。


namespaces:
<#import "/lib/my_test.ftl" as my> <#-- the hashcalled "my" will be the "gate" -->
<@my.copyright date="1999-2002"/>
${my.mail} 

设置命名空间里面的变量:<#assignmail="[email protected]" in my>

命名空间与数据模型:命名空间的ftl可以访问数据模型的变量。同样命名空间的变量也会隐藏数据模型中同名的变量。

空白问题:
1:White-space stripping,默认为enabled,清除ftl标记带来的空白以及缩进。处理模板的空白。
2:t, rt, lt指令。
3:ftl的参数strip_text.

用compress directive或者transform来处理输出。
<#compress>...:消除空白行。
<@compress single_line=true>.../@compress将输出压缩为一行。

可替换语法:
freemarker可用"["代替"<".在模板的文件开头加上[#ftl].

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1791781

Spring MVC 使用 Freemarker

·        Freemaker是取代JSP的又一种视图技术,和Velocity非常类似,但是它比Velocity多了一个格式化的功能,因此使用上较Velocity方便一点,但语法也稍微复杂一些。

将Velocity替换为Freemarker只需要改动一些配置文件,同样,在Spring中使用Freemarker也非常方便,根本无须与Freemarker的API打交道。我们将Spring_Velocity工程复制一份,命名为Spring_Freemarker,结构如图7-44所示。

图7-44 

修改dispatcher-servlet.xml,将velocityConfig删除,修改viewResolver为FreeMarker ViewResolver,并添加一个freemarkerConfig。

   

   

   

   

   

   

模板test.html可以稍做修改,加入Freemarker内置的格式化功能来定制Date类型的输出格式。

   

   Spring_Freemarker

   

Hello, ${name}, it is${time?string("yyyy-MM-dd HH:mm:ss")}

添加freemarker.jar到web/WEB-INF/lib目录后,启动Resin,可以看到由Freemarker渲染的页面

 

 

FreeMarker入门文章引用自:

1、快速入门
(1)模板 + 数据模型 = 输出

l         FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念
l         他们是分工劳动的:设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;程序员创建系统,生成设计页面要显示的数据
l         经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的
l         在这里,你可以在HTML(或其它要输出的文本)中加入一些特定指令,FreeMarker会在输出页面给最终用户时,用适当的数据替代这些代码
l         下面是一个例子:


  Welcome!


  

Welcome ${user}!


  

Our latest product:
  ${latestProduct.name}!

  
l         这个例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码是FreeMarker的指令,而包含FreeMarker的指令的文件就称为模板(Template)
l         至于user、latestProduct.url和latestProduct.name来自于数据模型(data model)
l         数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成
l         模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型
l         下面是一个可能的数据模型:
(root)
  |
  +- user = "Big Joe"
  |
  +- latestProduct
      |
      +- url ="products/greenmouse.html"
      |
      +- name = "green mouse"
l         数据模型类似于计算机的文件系统,latestProduct可以看作是目录,而user、url和name看作是文件,url和name文件位于latestProduct目录中(这只是一个比喻,实际并不存在)
l         当FreeMarker将上面的数据模型合并到模板中,就创建了下面的输出:


  Welcome!


  

Welcome Big Joe!


  

Our latest product:
  greenmouse!

  
(2)数据模型
l         典型的数据模型是树型结构,可以任意复杂和深层次,如下面的例子:
(root)
  |
  +- animals
  |   |
  |   +- mouse
  |   |   |  
  |   |   +- size = "small"
  |   |   |  
  |   |   +- price = 50
  |   |
  |   +- elephant
  |   |   |  
  |   |   +- size = "large"
  |   |   |  
  |   |   +- price = 5000
  |   |
  |   +- python
  |       |  
  |       +- size = "medium"
  |       |  
  |       +- price = 4999
  |
  +- test = "It is a test"
  |
  +- whatnot
      |
      +- because = "don't know"
l         类似于目录的变量称为hashes,包含保存下级变量的唯一的查询名字
l         类似于文件的变量称为scalars,保存单值
l         scalars保存的值有两种类型:字符串(用引号括起,可以是单引号或双引号)和数字(不要用引号将数字括起,这会作为字符串处理)
l         对scalars的访问从root开始,各部分用“.”分隔,如animals.mouse.price
l         另外一种变量是sequences,和hashes类似,只是不使用变量名字,而使用数字索引,如下面的例子:
(root)
  |
  +- animals
  |   |
  |   +- (1st)
  |   |   |
  |   |   +- name = "mouse"
  |   |   |
  |   |   +- size = "small"
  |   |   |
  |   |   +- price = 50
  |   |
  |   +- (2nd)
  |   |   |
  |   |   +- name = "elephant"
  |   |   |
  |   |   +- size = "large"
  |   |   |
  |   |   +- price = 5000
  |   |
  |   +- (3rd)
  |       |
  |       +- name = "python"
  |       |
  |       +- size = "medium"
  |       |
  |       +- price = 4999
  |
  +- whatnot
      |
      +- fruits
          |
          +- (1st) ="orange"
          |
          +- (2nd) ="banana"
l         这种对scalars的访问使用索引,如animals[0].name
(3)模板
l         在FreeMarker模板中可以包括下面三种特定部分:
?         ${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代
?         FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分,用#开始(有些以@开始,在后面叙述)
?         注释:包含在<#--和-->(而不是)之间
l         下面是一些使用指令的例子:
?         if指令
<#if animals.python.price < animals.elephant.price>
  Pythons are cheaper than elephants today.
<#else>
  Pythons are not cheaper than elephants today.
  
?         list指令

We have these animals:


  
NamePrice
  <#list animals as being>
  
${being.name}${being.price} Euros
  
  
输出为:

We have these animals:


  
NamePrice
  
mouse50 Euros
  
elephant5000 Euros
  
python4999 Euros
  
?         include指令


  Test page


  

Test page


  

Blah blah...
<#include "/copyright_footer.html">

  
?         一起使用指令

We have these animals:


  
    
NamePrice
  <#list animals as being>
  

      <#if being.size ="large">
      ${being.name}
      <#if being.size = "large">

    
${being.price} Euros
  
  

FreeMarker设计指南

快速入门

(1)模板 + 数据模型 = 输出 
FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念他们是分工劳动的:
设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;
程序员创建系统,生成设计页面要显示的数据。
经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的。在这里,你可以在HTML(或其它要输出的文本)中加入一些特定指令,FreeMarker会在输出页面给最终用户时,用适当的数据替代这些代码。
 
先来解释一下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  调用宏,并处理宏的嵌套
<#assign var = value > 定义变量并初始化
<#local var = value> 在 macro 或者 function 中定义局部变量并初始化
<#global var = value > 定义全局变量并初始化
${var} 输出并替换为表达式的值
<#visit xmlnode> 调用macro匹配xmlnode本身及其子节点
<#recurse xmlnode> 调用macro匹配xmlnode的子节点
 
下面是一个例子: 


  Welcome!


  

Welcome ${user}!

 

Our latest product:   ${latestProduct.name}!  

这个例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码是FreeMarker的指令,而包含FreeMarker的指令的文件就称为模板(Template)。
至于user、latestProduct.url和latestProduct.name来自于数据模型(data model)。
数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成。
模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型。
下面是一个可能的数据模型: 
(root)
  |
  +- user = "Big Joe"
  |
  +- latestProduct
      |
      +- url = "products/greenmouse.html"
      |
      +- name = "green mouse"
数据模型类似于计算机的文件系统,latestProduct可以看作是目录。 
2、数据模型 
(1)基础 
在快速入门中介绍了在模板中使用的三种基本对象类型:scalars、hashes 和sequences,其实还可以有其它更多的能力: 
scalars:存储单值 
hashes:充当其它对象的容器,每个都关联一个唯一的查询名字 
sequences:充当其它对象的容器,按次序访问 
方法:通过传递的参数进行计算,以新对象返回结果 
用户自定义FTL标记:宏和变换器 
通常每个变量只具有上述的一种能力,但一个变量可以具有多个上述能力,如下面的例子: 
(root)
 |
 +- mouse = "Yerri"
     |
     +- age = 12
     |
     +- color = "brown">  
mouse既是scalars又是hashes,将上面的数据模型合并到下面的模板: 
${mouse}       <#-- use mouse as scalar -->
${mouse.age}   <#-- use mouse as hash -->
${mouse.color} <#-- use mouse as hash -->  
输出结果是: 
Yerri
12
brown  
(2)Scalar变量 
Scalar变量存储单值,可以是: 
字符串:简单文本,在模板中使用引号(单引号或双引号)括起 
数字:在模板中直接使用数字值 
日期:存储日期/时间相关的数据,可以是日期、时间或日期-时间(Timestamp);通常情况,日期值由程序员加到数据模型中,设计者只需要显示它们 
布尔值:true或false,通常在<#if …>标记中使用 
(3)hashes 、sequences和集合 
有些变量不包含任何可显示的内容,而是作为容器包含其它变量,者有两种类型: 
hashes:具有一个唯一的查询名字和它包含的每个变量相关联 
sequences:使用数字和它包含的每个变量相关联,索引值从0开始 
集合变量通常类似sequences,除非无法访问它的大小和不能使用索引来获得它的子变量;集合可以看作只能由<#list …>指令使用的受限sequences 
(4)方法 
方法变量通常是基于给出的参数计算值。 
下面的例子假设程序员已经将方法变量avg放到数据模型中,用来计算数字平均值: 
The average of 3 and 5 is: ${avg(3, 5)}
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
The average of the price of python and elephant is: 
    ${avg(animals.python.price, animals.elephant.price)}
(5)宏和变换器 
宏和变换器变量是用户自定义指令(自定义FTL标记),会在后面讲述这些高级特性 
(6)节点 
节点变量表示为树型结构中的一个节点,通常在XML处理中使用,会在后面的专门章节中讲 
3、模板 
(1)整体结构 
模板使用FTL(FreeMarker模板语言)编写,是下面各部分的一个组合: 
文本:直接输出 
Interpolation:由${和},或#{和}来限定,计算值替代输出 
FTL标记:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出 
注释:由<#--和-->限定,不会输出 
下面是以一个具体模板例子: 


  Welcome!


  <#-- Greet the user with his/her name -->
  

Welcome ${user}!

 

We have these animals:  

      <#list animals as being>    
  • ${being.name} for ${being.price} Euros    
 
注意事项: 
FTL区分大小写,所以list是正确的FTL指令,而List不是;${name}和${NAME}是不同的 
Interpolation只能在文本中使用 
FTL标记不能位于另一个FTL标记内部,例如: 
<#if <#include 'foo'>='bar'>...
注释可以位于FTL标记和Interpolation内部,如下面的例子: 

Welcome ${user <#-- The name of user -->}!

We have these animals:

    <#list <#-- some comment... --> animals as <#-- again... --> being> ... 
余的空白字符会在模板输出时移除 
(2)指令 
在FreeMarker中,使用FTL标记引用指令。有三种FTL标记,这和HTML标记是类似的: 
开始标记:<#directivename parameters> 
结束标记: 
空内容指令标记:<#directivename parameters/> 
有两种类型的指令:预定义指令和用户定义指令。 
用户定义指令要使用@替换#,如<@mydirective>...(会在后面讲述)。 
FTL标记不能够交叉,而应该正确的嵌套,如下面的代码是错误的: 
    <#list animals as being>  
  • ${being.name} for ${being.price} Euros   <#if use = "Big Joe">      (except for you) <#-- WRONG! -->
 
如果使用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息。 
FreeMarker会忽略FTL标记中的空白字符,如下面的例子: 
<#list
  animals       as
     being
>
${being.name} for ${being.price} Euros
  
但是,<、 
  
(3)表达式 
直接指定值 
字符串 
使用单引号或双引号限定 
如果包含特殊字符需要转义,如下面的例子: 
${"It's \"quoted\" and
this is a backslash: \\"}

${'It\'s "quoted" and
this is a backslash: \\'} 
输出结果是: 
It's "quoted" and
this is a backslash: \

It's "quoted" and
this is a backslash: \ 
下面是支持的转义序列: 
转义序列 
含义 
\" 
双引号(u0022) 
\' 
单引号(u0027) 
 
反斜杠(u005C) 
\n 
换行(u000A) 
\r 
Return (u000D) 
\t 
Tab (u0009) 
\b 
Backspace (u0008) 
\f 
Form feed (u000C) 
\l 
< 
\g 
> 
\a 
& 
\{ 
{ 
\xCode 
4位16进制Unicode代码 
有一类特殊的字符串称为raw字符串,被认为是纯文本,其中的\和{等不具有特殊含义,该类字符串在引号前面加r,下面是一个例子: 
${r"${foo}"}

${r"C:\foo\bar"}  
输出的结果是: 
${foo}

C:\foo\bar  
数字 
直接输入,不需要引号 
精度数字使用“.”分隔,不能使用分组符号 
目前版本不支持科学计数法,所以“1E3”是错误的 
不能省略小数点前面的0,所以“.5”是错误的 
数字8、+8、08和8.00都是相同的 
布尔值 
true和false,不使用引号 
序列 
由逗号分隔的子变量列表,由方括号限定,下面是一个例子: 
<#list ["winter", "spring", "summer", "autumn"] as x>
${x}
 
输出的结果是: 
winter
spring
summer
autumn
列表的项目是表达式,所以可以有下面的例子: 
[2 + 2, [1, 2, 3, 4], "whatnot"]
可以使用数字范围定义数字序列,例如2..5等同于[2, 3, 4, 5],但是更有效率,注意数字范围没有方括号 
可以定义反递增的数字范围,如5..2 
散列(hash) 
由逗号分隔的键/值列表,由大括号限定,键和值之间用冒号分隔,下面是一个例子: 
{"name":"green mouse", "price":150}
键和值都是表达式,但是键必须是字符串 
获取变量 
顶层变量: ${variable},变量名只能是字母、数字、下划线、$、@和#的组合,且不能以数字开头 
从散列中获取数据 
可以使用点语法或方括号语法,假设有下面的数据模型: 
(root)
 |
 +- book
 |   |
 |   +- title = "Breeding green mouses"
 |   |
 |   +- author
 |       |
 |       +- name = "Julia Smith"
 |       |
 |       +- info = "Biologist, 1923-1985, Canada"
 |
 +- test = "title" 
下面都是等价的: 
book.author.name
book["author"].name
book.author.["name"]
book["author"]["name"]
使用点语法,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字是任意表达式的结果 
从序列获得数据:和散列的方括号语法语法一样,只是方括号中的表达式值必须是数字;注意:第一个项目的索引是0 
序列片断:使用[startIndex..endIndex]语法,从序列中获得序列片断(也是序列);startIndex和endIndex是结果为数字的表达式 
特殊变量:FreeMarker内定义变量,使用.variablename语法访问 
字符串操作 
Interpolation(或连接操作) 
可以使用${..}(或#{..})在文本部分插入表达式的值,例如: 
${"Hello ${user}!"}

${"${user}${user}${user}${user}"}  
可以使用+操作符获得同样的结果 
${"Hello " + user + "!"}

${user + user + user + user}
${..}只能用于文本部分,下面的代码是错误的: 
<#if ${isBig}>Wow!

<#if "${isBig}">Wow!
应该写成: 
<#if isBig>Wow!
子串 
例子(假设user的值为“Big Joe”): 
${user[0]}${user[4]}

${user[1..4]}
结果是(注意第一个字符的索引是0): 
BJ

ig J 
序列操作 
连接操作:和字符串一样,使用+,下面是一个例子: 
<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
- ${user}
输出结果是: 
- Joe
- Fred
- Julia
- Kate
散列操作 
连接操作:和字符串一样,使用+,如果具有相同的key,右边的值替代左边的值,例如: 
<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
- Joe is ${ages.Joe}
- Fred is ${ages.Fred}
- Julia is ${ages.Julia}  
输出结果是: 
- Joe is 30
- Fred is 25
- Julia is 18  
算术运算 
+、-、×、/、%,下面是一个例子: 
${x * x - 100}
${x / 2}
${12 % 10}
输出结果是(假设x为5): 
-75
2.5
2  
操作符两边必须是数字,因此下面的代码是错误的: 
${3 * "5"} <#-- WRONG! -->  
使用+操作符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串,例如: 
${3 + "5"}  
输出结果是: 
35
使用内建的int(后面讲述)获得整数部分,例如: 
${(x/2)?int}
${1.1?int}
${1.999?int}
${-1.1?int}
${-1.999?int}
输出结果是(假设x为5): 
2
1
1
-1
-1
比较操作符 
使用=(或==,完全相等)测试两个值是否相等,使用!= 测试两个值是否不相等 
=和!=两边必须是相同类型的值,否则会产生错误,例如<#if 1 = "1">会引起错误 
Freemarker是精确比较,所以对"x"、"x "和"X"是不相等的 
对数字和日期可以使用<、<=、>和>=,但不能用于字符串 
由于Freemarker会将>解释成FTL标记的结束字符,所以对于>和>=可以使用括号来避免这种情况,例如<#if (x > y)> 
另一种替代的方法是,使用lt、lte、gt和gte来替代<、<=、>和>= 
逻辑操作符 
&&(and)、||(or)、!(not),只能用于布尔值,否则会产生错误 
例子: 
<#if x < 12 && color = "green">
  We have less than 12 things, and they are green.

<#if !hot> <#-- here hot must be a boolean -->
  It's not hot.
  
内建函数 
内建函数的用法类似访问散列的子变量,只是使用“?”替代“.”,下面列出常用的一些函数 
 
字符串使用的: 
html:对字符串进行HTML编码 
cap_first:使字符串第一个字母大写 
lower_case:将字符串转换成小写 
upper_case:将字符串转换成大写 
trim:去掉字符串前后的空白字符 
 
序列使用的: 
size:获得序列中元素的数目 
 
数字使用的: 
int:取得数字的整数部分(如-1.9?int的结果是-1) 
例子(假设test保存字符串"Tom & Jerry"): 
${test?html}
${test?upper_case?html}
输出结果是: 
Tom & Jerry
TOM & JERRY  
操作符优先顺序 
操作符组 
操作符 
后缀 
[subvarName] [subStringRange] . (methodParams) 
一元 
+expr、-expr、! 
内建 
? 
乘法 
*、 / 、% 
加法 
+、- 
关系 
<、>、<=、>=(lt、lte、gt、gte) 
相等 
==(=)、!= 
逻辑and 
&& 
逻辑or 
双竖线
数字范围 
.. 
(4)Interpolation 
Interpolation有两种类型: 
通用Interpolation:${expr} 
数字Interpolation:#{expr}或#{expr; format} 
注意:Interpolation只能用于文本部分 
通用Interpolation 
插入字符串值:直接输出表达式结果 
插入数字值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个例子: 
<#setting number_format="currency"/>
<#assign answer=42/>
${answer}
${answer?string}  <#-- the same as ${answer} -->
${answer?string.number}
${answer?string.currency}
${answer?string.percent} 
输出结果是: 
$42.00
$42.00
42
$42.00
4,200%
插入日期值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个使用格式模式的例子: 
${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}
${lastUpdated?string("EEE, MMM d, ''yy")}
${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}  
输出的结果类似下面的格式: 
2003-04-08 21:24:44 Pacific Daylight Time
Tue, Apr 8, '03
Tuesday, April 08, 2003, 09:24:44 PM (PDT)
插入布尔值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个例子: 
<#assign foo=true/>
${foo?string("yes", "no")}
输出结果是: 
yes
数字Interpolation的#{expr; format}形式可以用来格式化数字,format可以是: 
mX:小数部分最小X位 
MX:小数部分最大X位 
例子: 
<#-- If the language is US English the output is: -->
<#assign x=2.582/>
<#assign y=4/>
#{x; M2}   <#-- 2.58 -->
#{y; M2}   <#-- 4    -->
#{x; m1}   <#-- 2.6 -->
#{y; m1}   <#-- 4.0 -->
#{x; m1M2} <#-- 2.58 -->
#{y; m1M2} <#-- 4.0  -->  
4、杂项 
(1)用户定义指令 
宏和变换器变量是两种不同类型的用户定义指令,它们之间的区别是宏是在模板中使用macro指令定义,而变换器是在模板外由程序定义,这里只介绍宏 
基本用法 
宏是和某个变量关联的模板片断,以便在模板中通过用户定义指令使用该变量,下面是一个例子: 
<#macro greet>
  Hello Joe!
  
作为用户定义指令使用宏变量时,使用@替代FTL标记中的# 
<@greet>
如果没有体内容,也可以使用: 
<@greet/>
参数 
在macro指令中可以在宏变量之后定义参数,如: 
<#macro greet person>
  Hello ${person}!
 
可以这样使用这个宏变量: 
<@greet person="Fred"/> and <@greet person="Batman"/> 
输出结果是: 
  Hello Fred!

 and   Hello Batman!
宏的参数是FTL表达式,所以下面的代码具有不同的意思: 
<@greet person=Fred/>
这意味着将Fred变量的值传给person参数,该值不仅是字符串,还可以是其它类型,甚至是复杂的表达式 
可以有多参数,下面是一个例子: 
<#macro greet person color>
  Hello ${person}!
 
可以这样使用该宏变量: 
<@greet person="Fred" color="black"/> 
其中参数的次序是无关的,因此下面是等价的: 
<@greet color="black" person="Fred"/>
只能使用在macro指令中定义的参数,并且对所有参数赋值,所以下面的代码是错误的: 
<@greet person="Fred" color="black" background="green"/>
<@greet person="Fred"/>
可以在定义参数时指定缺省值,如: 
<#macro greet person color="black">
  Hello ${person}!
  
这样<@greet person="Fred"/>就正确了 
宏的参数是局部变量,只能在宏定义中有效 
嵌套内容 
用户定义指令可以有嵌套内容,使用<#nested>指令执行指令开始和结束标记之间的模板片断 
例子: 
<#macro border>
  
    <#nested>  
 
这样使用该宏变量: 
<@border>The bordered text
输出结果: 
  
    The bordered text  
<#nested>指令可以被多次调用,例如: 
<#macro do_thrice>
  <#nested>
  <#nested>
  <#nested>

<@do_thrice>
  Anything.
  
输出结果: 
  Anything.
  Anything.
  Anything. 
嵌套内容可以是有效的FTL,下面是一个有些复杂的例子: <@border> 
    <@do_thrice>
  • <@greet person="Joe"/>
}}}
输出结果:
  
     
       
  • Hello Joe!    
  • Hello Joe!    
  • Hello Joe!  
 
 
宏定义中的局部变量对嵌套内容是不可见的,例如: 
<#macro repeat count>
  <#local y = "test">
  <#list 1..count as x>
    ${y} ${count}/${x}: <#nested>
  

<@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}
输出结果: 
    test 3/1: ? ? ?
    test 3/2: ? ? ?
    test 3/3: ? ? ?
在宏定义中使用循环变量 
用户定义指令可以有循环变量,通常用于重复嵌套内容,基本用法是:作为nested指令的参数传递循环变量的实际值,而在调用用户定义指令时,在<@…>开始标记的参数后面指定循环变量的名字 
例子: 
<#macro repeat count>
  <#list 1..count as x>
    <#nested x, x/2, x==count>
  

<@repeat count=4 ; c, halfc, last>
  ${c}. ${halfc}<#if last> Last!
  
输出结果: 
  1. 0.5
  2. 1
  3. 1.5
  4. 2 Last!
指定的循环变量的数目和用户定义指令开始标记指定的不同不会有问题 
调用时少指定循环变量,则多指定的值不可见 
调用时多指定循环变量,多余的循环变量不会被创建 
(2)在模板中定义变量 
在模板中定义的变量有三种类型: 
plain变量:可以在模板的任何地方访问,包括使用include指令插入的模板,使用assign指令创建和替换 
局部变量:在宏定义体中有效,使用local指令创建和替换 
循环变量:只能存在于指令的嵌套内容,由指令(如list)自动创建 
宏的参数是局部变量,而不是循环变量;局部变量隐藏(而不是覆盖)同名的plain变量;循环变量隐藏同名的局部变量和plain变量,下面是一个例子: 
<#assign x = "plain">
1. ${x}  <#-- we see the plain var. here -->
<@test/>
6. ${x}  <#-- the value of plain var. was not changed -->
<#list ["loop"] as x>
  7. ${x}  <#-- now the loop var. hides the plain var. -->
<#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
 8. ${x}  <#-- it still hides the plain var. -->

   9. ${x}  <#-- the new value of plain var. -->
<#macro test>
  2. ${x}  <#-- we still see the plain var. here -->
  <#local x = "local">
  3. ${x}  <#-- now the local var. hides it -->
  <#list ["loop"] as x>
    4. ${x}  <#-- now the loop var. hides the local var. -->
  
  5. ${x}  <#-- now we see the local var. again -->
  
输出结果: 
1. plain
  2. plain
  3. local
    4. loop
  5. local
6. plain
    7. loop
    8. loop
9. plain2
内部循环变量隐藏同名的外部循环变量,如: 
<#list ["loop 1"] as x>
  ${x}
  <#list ["loop 2"] as x>
    ${x}
    <#list ["loop 3"] as x>
      ${x}
    
    ${x}
  
  ${x}
输出结果: 
  loop 1
    loop 2
      loop 3
    loop 2
  loop 1 
模板中的变量会隐藏(而不是覆盖)数据模型中同名变量,如果需要访问数据模型中的同名变量,使用特殊变量global,下面的例子假设数据模型中的user的值是Big Joe: 
<#assign user = "Joe Hider">
${user}          <#-- prints: Joe Hider -->
${.globals.user} <#-- prints: Big Joe -->  
(3)名字空间 
通常情况,只使用一个名字空间,称为主名字空间 
为了创建可重用的宏、变换器或其它变量的集合(通常称库),必须使用多名字空间,其目的是防止同名冲突 
创建库 
下面是一个创建库的例子(假设保存在lib/my_test.ftl中): 
<#macro copyright date>
  

Copyright (C) ${date} Julia Smith. All rights reserved.  
Email: ${mail}

  <#assign mail = "[email protected]">
使用import指令导入库到模板中,Freemarker会为导入的库创建新的名字空间,并可以通过import指令中指定的散列变量访问库中的变量: 
<#import "/lib/my_test.ftl" as my>
<#assign mail="[email protected]">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}  
输出结果: 
  

Copyright (C) 1999-2002 Julia Smith. All rights reserved.  
Email: [email protected]

[email protected] [email protected]  
可以看到例子中使用的两个同名变量并没有冲突,因为它们位于不同的名字空间 
可以使用assign指令在导入的名字空间中创建或替代变量,下面是一个例子: 
<#import "/lib/my_test.ftl" as my>
${my.mail}
<#assign mail="[email protected]" in my>
${my.mail}  
输出结果: 
[email protected]
[email protected]  
数据模型中的变量任何地方都可见,也包括不同的名字空间,下面是修改的库: 
<#macro copyright date>
  

Copyright (C) ${date} ${user}. All rights reserved.

<#assign mail = "${user}@acme.com">  
假设数据模型中的user变量的值是Fred,则下面的代码: 
<#import "/lib/my_test.ftl" as my>
<@my.copyright date="1999-2002"/>
${my.mail}   
输出结果: 
  

Copyright (C) 1999-2002 Fred. All rights reserved.

[email protected]   补充(静态方法的调用): 方法1: ##定义配置文件 freemarkerstatic.properties _Validator=com.longyou.util.Validator _Functions=com.longyou.util.Functions _EscapeUtils=com.longyou.util.EscapeUtils /调用代码 ${_Functions.toUpperCase("Hello")}
${_EscapeUtils.escape("狼的原野")} 方法2: ${stack.findValue("@package.ClassName@method")} 补充:常用语法
EG.一个对象BOOK
1.输出 ${book.name}
空值判断:${book.name?if_exists },
${book.name?default(‘xxx’)}//默认值xxx
${ book.name!"xxx"}//默认值xxx
日期格式:${book.date?string('yyyy-MM-dd')}
数字格式:${book?string.number}--20
${book?string.currency}--<#-- $20.00 -->
${book?string.percent}—<#-- 20% -->
插入布尔值:
<#assign foo=ture />
${foo?string("yes","no")} <#-- yes -->
 
 
 
 
2.逻辑判断
a:
<#if condition>...
<#elseif condition2>...
<#elseif condition3>......
<#else>...
其中空值判断可以写成<#if book.name?? >
 
b:
<#switch value>
<#case refValue1>
...
<#break>
<#case refValue2>
...
<#break>
...
<#case refValueN>
...
<#break>
<#default>
...
 
3.循环读取
<#list sequence as item>
...
空值判断<#if bookList?size = 0>
e.g.
<#list employees as e>
${e_index}. ${e.name}
输出:
1. Readonly
2. Robbin

freemarker中Map的使用
<#list testMap?keys as testKey> 
       < option value="${testKey}" > 
              ${testMap[testKey]} 
      
freemarker的Eclipse插件
If you use Eclipse 2.x: 
Open the Window menu, then Open Perspective -> Install/Update 
Click with the right mouse button on the Feature Updates view, then select New -> Site Bookmark 
In the displayed dialog box, type "FreeMarker" for Name and "http://www.freemarker.org/eclipse/update" for URL. Leave the "Bookmark type" radio buttons on "Eclipse update site". 
Click Finish 
Open the tree node under the newly created update site named "FreeMarker", select the "FreeMarker X.Y.Z" feature, and install it using the Install now button in the preview pane. 
If you use Eclipse 3.x: 
Help -> Software updates -> Find and install.... 
Choose "Search for new features to install". 
Click Add Update Site..., and type "FreeMarker" for Name and "http://www.freemarker.org/eclipse/update" for URL. 
Check the box of the "FreeMarker" feature. 
"Next"-s until it is installed... 
关键字: FreeMarker  
引用地址: http://www.dlog.cn/html/trackback.do?id=13925&type=1 (复制地址) 

FreeMarker设计指南(2)  

2、数据模型

(1)基础

        在快速入门中介绍了在模板中使用的三种基本对象类型:scalars、hashes 和sequences,其实还可以有其它更多的能力:

        scalars:存储单值

        hashes:充当其它对象的容器,每个都关联一个唯一的查询名字

        sequences:充当其它对象的容器,按次序访问

        方法:通过传递的参数进行计算,以新对象返回结果

        用户自定义FTL标记:宏和变换器

        通常每个变量只具有上述的一种能力,但一个变量可以具有多个上述能力,如下面的例子:

(root)

 |

 +-mouse = "Yerri"

    |

    +- age = 12

    |

    +- color = "brown"> 

        mouse既是scalars又是hashes,将上面的数据模型合并到下面的模板:

${mouse}       <#-- use mouse as scalar -->

${mouse.age}   <#-- use mouse as hash -->

${mouse.color} <#-- use mouse as hash--> 

        输出结果是:

Yerri

12

brown 

(2)Scalar变量

        Scalar变量存储单值,可以是:

        字符串:简单文本,在模板中使用引号(单引号或双引号)括起

        数字:在模板中直接使用数字值

        日期:存储日期/时间相关的数据,可以是日期、时间或日期-时间(Timestamp);通常情况,日期值由程序员加到数据模型中,设计者只需要显示它们

        布尔值:true或false,通常在<#if …>标记中使用

(3)hashes 、sequences和集合

        有些变量不包含任何可显示的内容,而是作为容器包含其它变量,者有两种类型:

        hashes:具有一个唯一的查询名字和它包含的每个变量相关联

        sequences:使用数字和它包含的每个变量相关联,索引值从0开始

        集合变量通常类似sequences,除非无法访问它的大小和不能使用索引来获得它的子变量;集合可以看作只能由<#list…>指令使用的受限sequences

(4)方法

        方法变量通常是基于给出的参数计算值

        下面的例子假设程序员已经将方法变量avg放到数据模型中,用来计算数字平均值:

The average of 3 and 5 is: ${avg(3, 5)}

The average of 6 and 10 and 20 is: ${avg(6,10, 20)}

The average of the price of python andelephant is: ${avg(animals.python.price, animals.elephant.price)}

(5)宏和变换器

        宏和变换器变量是用户自定义指令(自定义FTL标记),会在后面讲述这些高级特性

(6)节点

        节点变量表示为树型结构中的一个节点,通常在XML处理中使用,会在后面的专门章节中讲述




Trackback:http://tb.blog.csdn.net/TrackBack.aspx?PostId=164465

 

 

解析FreeMarker视图

·        解析FreeMarker视图

 

声明一个针对FreeMarker的视图解析器:

 

           web.servlet.view.freemarker.FreeMarkerViewResolver">

    .ftl

 

 

FreeMarkerViewResolver和VelocityViewResolver或InternalResourceViewResolver的工作机制相同。模板资源是通过在视图的逻辑名上增加prefix属性的值作为前缀,以及增加suffix属性的值作为后缀进行解析的。和VelocityViewResolver一样,在这里我们又一次只设置suffix属性,因为模板的路径已经在FreeMarkerConfigurer的templateLoaderPath属性中定义了。

暴露请求和会话属性

在第9.1.3节中,你看到如何告诉VelocityViewResolver将请求和会话属性复制到模型map中,从而它们能够在模板中作为变量使用。采用同样的方式配置FreeMarkerViewResolver,可以将请求和会话属性作为变量暴露给FreeMarker模板使用。要做到这一点,可以设置exposeRequestAttributes或者exposeSessionAttributes为true:

 

           web.servlet.view.freemarker.FreeMarkerViewResolver">

 

   

      true

   

   

      true

   

 

 

这里,两个属性都被设置为true。结果是请求和会话属性都被复制到模板的属性集中,可以使用FreeMarker的表达式语言来访问并显示。

 

FreeMarker文章引用自:

发表时间:2007年11月2日 16时54分13秒        本文链接:http://user.qzone.qq.com/55117942/blog/1193993653评论/阅读(0/5)

[顶]FreeMarker

包含FreeMarker的指令的文件就称为模板(Template)。

  包含FreeMarker的指令的文件就称为模板(Template)。
模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型。
数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成。

数据类型:

一、基本:
1、scalars:存储单值

字符串:简单文本由单或双引号括起来。
数字:直接使用数值。
日期:通常从数据模型获得
布尔值:true或false,通常在<#if …>标记中使用

2、hashes:充当其它对象的容器,每个都关联一个唯一的查询名字

具有一个唯一的查询名字和他包含的每个变量相关联。

3、sequences:充当其它对象的容器,按次序访问

使用数字和他包含的每个变量相关联。索引值从0开始。

4、集合变量:

除了无法访问它的大小和不能使用索引来获得它的子变量:集合可以看作只能由<#list...>指令使用的受限sequences。

5、方法:通过传递的参数进行计算,以新对象返回结果

方法变量通常是基于给出的参数计算值在数据模型中定义。

6、用户自定义FTL指令:宏和变换器

7、节点

节点变量表示为树型结构中的一个节点,通常在XML处理中使用。

模板:

使用FTL(freeMarker模板语言)编写

组成部分

一、整体结构

1、注释:<#--注释内容-->,不会输出。

2、文本:直接输出。

3、interpolation:由 ${var} 或 #{var} 限定,由计算值代替输出。

4、FTL标记

二、指令:
freemarker指令有两种:
1、预定义指令:引用方式为<#指令名称>
2、用户定义指令:引用方式为<@指令名称>,引用用户定义指令时须将#换为@。
注意:如果使用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息。

freemarker指令由FTL标记来引用,FTL标记和HTML标记类似,名字前加#来加以区分。如HTML标记的形式为

则FTL标记的形式是<#list>(此处h1标记和list指令没有任何功能上的对应关系,只是做为说明使用一下)。

有三种FTL标记:
1)、开始标记:<#指令名称>
2)、结束标记:
3)、空标记:<#指令名称/>

注意:

1) FTL会忽略标记之中的空格,但是,<#和指令 与 2) FTL标记不能够交叉,必须合理嵌套。每个开始标记对应一个结束标记,层层嵌套。 如:
<#list>

  • ${数据}
    <#if 变量>

    game over!






  • 注意事项:
    1)、FTL对大小写敏感。所以使用的标记及interpolation要注意大小写。name与NAME就是不同的对象。<#list>是正确的标记,而<#List>则不是。
    2)、interpolation只能在文本部分使用,不能位于FTL标记内。如<#if ${var}>是错误的,正确的方法是:<#if var>,而且此处var必须为布尔值。
    3)、FTL标记不能位于另一个FTL标记内部,注释例外。注释可以位于标记及interpolation内部。


    三、表达式

    1、直接指定值:

    1-1、字符串:
    由双引号或单引号括起来的字符串,其中的特殊字符(如' " \等)需要转义。


    1-2、raw字符串:
    有一种特殊的字符串称为raw字符串,被认为是纯文本,其中的\和{等不具有特殊含义,该类字符串在引号前面加r,下面是一个例子:
    ${r"/${data}"year""}屏幕输出结果为:/${data}"year"


    转义    含义
    序列  

    \"  双引号(u0022)

    \'  单引号(u0027)

    \\  反斜杠(u005C)

    \n  换行(u000A)

    \r  Return (u000D)

    \t  Tab (u0009)

    \b  Backspace (u0008)

    \f  Form feed (u000C)

    \l  <

    \g  >

    \a  &

    \{  {

    \xCode  4位16进制Unicode代码

    1-3、数字:直接输入,不需要引号

    1)、精度数字使用“.”分隔,不能使用分组符号
    2)、目前版本不支持科学计数法,所以“1E3”是错误的
    3)、不能省略小数点前面的0,所以“.5”是错误的
    4)、数字8、+8、08和8.00都是相同的

    1-4、布尔值:true和false,不使用引号

    1-5、序列:由逗号分隔的子变量列表,由[]方括号限定。
    1)、子变量列表可以是表达式
    2)、可以使用数字范围定义数字序列,不需要方括号限定,例如2..5等同于[2, 3, 4, 5],但是更有效率,可以定义反递增范围如:5..2。

    1-6、散列(hash)
    1)、由逗号分隔的键/值列表,由{}大括号限定,键和值之间用冒号分隔,如:{"key1":valu1,"key2":"character string"....}
    2)、键和值都是表达式,但是键必须是字符串。

    2、获取变量:

    2-1、顶层变量:${变量名}

    变量名只能是字母、数字、下划线、$、#、@ 的组合,且不能以数字开头。

    2-2、散列:有两种方法

    1)、点语法:变量名字和顶层变量的名字受同样的限制
    2)、方括号语法:变量名字无限制,可以是任意的表达式的结果
    book.author.name
    book.author.["name"]
    book["author"].name
    book["author"]["name"]
    以上是等价的。

    2-3、序列:使用散列的方括号语法获取变量,方括号中的表达式结果必须为数字。注意:第一个项目的索引为0。可以使用
    [startindex..endindex]语法获取序列片段。

    2-4、特殊变量:FreeMarker内定义变量,使用.variablename语法访问。

    3、字符串操作

    3-1、interpolation:使用${}或#{}在文本部分插入表达式的值,例如:

    ${"hello${username}!"}
    ${"${username}${username}${username}"}

    也可以使用+来获得同样的结果:
    ${"hello"+username+"!"}
    ${username+username+username}

    注意:${}只能用于文本部分而不能出现于标记内。

    <#if ${user.login}>或<#if "${user.login}">都是错误的;
    <#if user.login>是正确的。
    本例中user.login的值必须是布尔类型。

    3-2、子串:
    举例说明:假如user的值为"Big Joe"
    ${user[0]}${user[4]}结果是:BJ
    ${user[1..4]}结果是:ig J

    4、序列操作

    4-1、连接操作:可以使用+来操作,例如:
    ["title","author"]+["month","day"]

    5、散列操作
    5-1、连接操作:可以使用+来操作,如果有相同的KEY,则右边的值会替代左边的值,例如:
    {"title":散列,"author":"emma"}+{"month":5,"day":5}+{"month":6}结果month的值就是6。

    6、算术运算

    6-1、操作符:+、-、*、/、%
    除+号以外的其他操作符两边的数据,必须都是数字类型。
    如果+号操作符一边有一个字符型数据,会自动将另一边的数据转换为字符型数据,运算结果为字符型数据。

    6-2、比较操作符:
    1)、=
    2)、==
    3)、!=
    4)、<
    5)、<=
    6)、>
    7)、>=
    1-3的操作符,两边的数据类型必须相同,否则会产生错误
    4-7的操作符,对于日期和数字可以使用,字符串不可以使用。

    注意:
    1)、FreeMarker是精确比较,所以"x" "x " "X"是不等的。
    2)、因为<和>对FTL来说是开始和结束标记,所以,可以用两种方法来避免这种情况:
    一种是使用括号<#if (a
    另一是使用替代输出,对应如下:
    <  lt
    <= lte
    >  gt
    >= gte

    6-3、逻辑操作符:只能用于布尔值,否则会出现错误。

    &&(and)与运算
    ||(or)或运算
    !(not)非运算

    6-4、内建函数:使用方法类似于访问散列的子变量,只是使用?代替.例如:${test?upper_case?html}

    常用的内建函数列举如下:

    1)、字符串使用:

    html:对字符串进行HTML编码
    cap_first:字符串第一个字母大写
    lower_first:字符串第一个字母小写
    upper_case:将字符串转换成大写
    trim:去年字符前后的空白字符

    2)、序列使用:
    size:获得序列中元素的数目

    3)、数字使用:
    int:取得数字的整数部分

    7、操作符的优先顺序:

    后缀:[subbarName][subStringRange].(mathodParams)
    一元:+expr、-expr、! (not)
    内建:?
    乘法:*、/、%
    加法:+、-
    关系:<、<=、>、>= (lt、lte、gt、gte)
    相等:=、==、!=
    逻辑与:&& (and)
    逻辑或:|| (or)
    数字范围:..

    四、interpolation

    inperpolation只能用于文本,有两种类型:通用interpolation及数字interpolation

    1、通用interpolation

    如${expr}

    1-1、插入字符串值:直接输出表达式结果。
    1-2、插入数字值:根据缺省格式(由setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string来格式化单个interpolation

    如:
    <#setting number_format="currency" />
    <#assign answer=42 />
    ${answer}  <#-- ¥42.00 -->
    ${answer?string}  <#-- ¥42.00 -->
    ${answer?string.number}  <#-- 42 -->
    ${answer?string.currency}  <#-- ¥42.00 -->
    ${answer?string.percent}  <#-- 42,00% -->

    1-3、插入日期值:根据缺省格式(由setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string来格式化单个interpolation

    如:

    ${lastupdata?string("yyyy-MM-dd HH:mm:ss zzzz")}  <#-- 2003-04-08 21:24:44 Pacific Daylight Time -->
    ${lastupdata?string("EEE,MMM d, ''yy")}  <#-- tue,Apr 8, '03 -->
    ${lastupdata?string("EEEE,MMMM dd, yyyy,hh:mm:ss a '('zzz')'")}  <#-- Tuesday,April 08, 2003, 09:24:44 PM (PDT)-->

    1-4、插入布尔值:根据缺省格式(由setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string来格式化单个interpolation

    如:
    <#assign foo=ture />
    ${foo?string("yes","no")} <#-- yes -->

    2、数字interpolation:

    有两种形式:
    1)、#{expr}
    2)、#{expr;format}:format可以用来格式化数字,format可以是如下:
    mX:小数部分最小X位
    MX:小数部分最大X位

    例如:
    <#assign x=2.582 />
    <#assign y=4 />
    #{x;M2} <#-- 2.58 -->
    #{y;M2} <#-- 4 -->
    #{x;m1} <#-- 2.582 -->
    #{y;m1} <#-- 4.0 -->
    #{x;m1M2} <#-- 2.58 -->
    #{y;m1M2} <#-- 4.0 -->


    杂项

    一、用户定义指令

    宏和变换器变量是两种不同类型的用户自定义指令,他们的区别是:

    宏可以在模板中用macro指令来定义
    变换器是在模板外由程序定义

    1、宏:和某个变量关联的模板片段,以便在模板中通过用户自定义指令使用该变量
    1-1、基本用法:
    例如:
    <#macro greet>
    Hello JOE!



    使用时:
    <@greet>
    如果没有体内容也可以用
    <@greet />

    1-2、变量:

    1)、可以在宏定义之后定义参数,宏参数是局部变量,只在宏定义中有效。如:

    <#macro greet person>
    Hello ${person}!

    使用时:
    <@greet person="emma"> and <@greet person="LEO">
    输出为:
    Hello emma!
    Hello LEO!

    注意:宏的参数是FTL表达式,所以,person=emma和上面的例子中具有不同的意义,这意味着将变量emma的值传给person,这个值可能是任意一种数据类型,甚至是一个复杂的表达式。


    宏可以有多个参数,使用时参数的次序是无关的,但是只能使用宏中定义的参数,并且对所有参数赋值。如:
    <#macro greet person color>
    Hello ${person}!


    使用时:
    <@greet color="black" person="emma" />正确
    <@greet person="emma" />错误,color没有赋值,此时,如果在定义宏时为color定义缺省值<#macro greet person color="black">这样的话,这个使用方法就是正确的。
    <@greet color="black" person="emma" bgcolor="yellow" />错误,宏greet定义中未指定bgcolor这个参数



    2、嵌套内容:

    2-1、自定义指令可以有嵌套内容,使用<#nested>指令,执行自定义指令开始和结束标记之间的模板片段。例如:
    <#macro greet>


    <#nested>





    <@greet>hello Emma!

    输出为

    hello Emma!



    2-2、<#nested>指令可以被多次调用,例如
    <#macro greet>


    <#nested>
    <#nested>
    <#nested>
    <#nested>




    <@greet>hello Emma!

    输出为


    hello Emma!
    hello Emma!
    hello Emma!
    hello Emma!



    2-3、嵌套的内容可以是有效的FTL,例如:
    <#macro welcome>


    <#nested>




    <#macro greet person color="black">
    Hello ${person}!


    <@welcome>
    <@greet person="Emma" color="red" />
    <@greet person="Andrew" />
    <@greet person="Peter" />


    输出为:


    Hello Emma!
    Hello Andrew!
    Hello Peter!



    2-4、宏定义中的局部变量对嵌套内容是不可见的,例如:

    <#macro repeat count>
    <#local y="test" />
    <#list 1..count as x>
    ${y}${count}/${x}:<#nested />



    <@repeat count=3>
    ${y?default("?")}
    ${x?default("?")}
    ${count?default("?")}


    输出结果为
    test 3/1:???
    test 3/2:???
    test 3/3:???

    2-5、在宏定义中使用循环变量,通常用来重复嵌套内容,基本用法为:作为nested指令的参数,传递循环变量的实际值,而在调用自定义指令时,在标记的参数后面指定循环变量的名字。
    例如:
    <#macro repeat count>
    <#list 1..count as x>
    <#nested x,x/2,x==count />



    <@repeat count=4;c,halfc,last>
    ${c}. ${halfc}
    <#if last>
    last!



    输出结果是

    1. 0.5
    2. 1
    3. 1.5
    4. 2last!

    注意:指定循环变量的数目和用户定义指令开始标记指定的不同不会有问题
    调用时,少指定循环变量,多指定的值会不见
    调用时,多指定循环变量,多余的循环变量不会被创建

    二、在模板中定义变量

    1、在模板中定义的变量有三种类型

    1-1、plain变量:可以在模板的任何地方访问,包括使用include指令插入的模板,使用assign指令创建和替换。
    1-2、局部变量:在宏定义体中有效,使用local指令创建和替换。
    1-3、循环变量:只能存在于指令的嵌套内容,由指令(如list)自动创建。

    注意:
    1)、宏的参数是局部变量,不是循环变量。
    2)、局部变量隐藏同名的plain变量
    3)、循环变量隐藏同名的plain变量和局部变量。

    例如:

    <#assign x="plain">
    1. ${x} <#-- plain -->

    <@test />

    6. ${x}
    <#list ["loop"] as x>
    7. ${x} <#-- loop -->
    <#assign x="plain2">
    8. ${x} <#-- loop -->

    9. ${x} <#-- plain2 -->

    <#macro test>
    2. ${x} <#-- plain -->
    <#local x="local">
    3. ${x} <#-- local -->
    <#list ["loop"] as x>
    4. ${x} <#-- loop -->

    5. ${x} <#-- local -->


    4)、内部循环变量隐藏同名的外部循环变量

    <#list ["loop1"] as x>
    ${x} <#-- loop1 -->
    <#list ["loop2"] as x>
    ${x} <#-- loop2 -->
    <#list ["loop3"] as x>
    ${x} <#-- loop3 -->

    ${x} <#-- loop2 -->

    ${x} <#-- loop1 -->


    5)、模板中的变量会隐藏数据模型中的同名变量,如果需访问数据模型中的变量,使用特殊变量global。

    例如:
    假设数据模型中的user值为Emma
    <#assign user="Man">
    ${user} <#-- Man -->
    ${.global.user} <#-- Emma -->

    数据源+freemarker+servlet生成xml文件  

    .步骤:

    1.server.xml文件中建立数据源.

    <Service name="Cms">
         <Connector debug="0" enableLookups="false" port="8084" protocol="AJP/1.3" redirectPort="8443"/>
        <Connector acceptCount="100" connectionTimeout="20000" debug="0" disableUploadTimeout="true" 

    enableLookups
    ="false" maxSpareThreads="75" maxThreads="150" minSpareThreads="25" port="8081" redirectPort="8443"/>
        <Engine defaultHost="localhost_Cms" name="Catalina_Cms">
          <Logger className="org.apache.catalina.logger.FileLogger" prefix="localhost_cmt_log." suffix=".txt" timestamp="true"/>
          <Realm className="org.apache.catalina.realm.UserDatabaseRealm"/>
          <Host autoDeploy="true" debug="0" name="localhost_Cms" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
             <Context debug="0" docBase="D:WorkspaceCMSweb" path="/" reloadable="true" workDir="D:WorkspaceCMSj2src"> 
              <Resource name="jdbc/news_DB" auth="Container" type="javax.sql.DataSource"/>
            <ResourceParams name="jdbc/news_DB">
         <parameter>
           <name>factoryname>
           
           <value>org.apache.commons.dbcp.BasicDataSourceFactoryvalue>
         parameter>
          
         <parameter>
           <name>maxActivename>
           <value>1000value>
         parameter>
         <parameter>
            <name>validationQueryname>
            <value>select 1+1value>
         parameter>
         <parameter>
           <name>maxIdlename>
           <value>100value>
         parameter>
         <parameter>
           <name>maxWaitname>
           <value>10000value>
         parameter>
         <parameter>
           <name>removeAbandonedname>
           <value>truevalue>
         parameter>
         <parameter>
           <name>removeAbandonedTimeoutname>
           <value>60value>
         parameter>
         <parameter>
           <name>logAbandonedname>
           <value>falsevalue>
         parameter>
          
         <parameter>
           <name>usernamename>
           <value>aaaavalue>
         parameter>
         <parameter>
           <name>passwordname>
           <value>bbbbbbvalue>
         parameter>
         <parameter>
           <name>driverClassNamename>
           <value>net.sourceforge.jtds.jdbc.Drivervalue>
         parameter>
         <parameter>
           <name>urlname>
           <value>jdbc:jtds:sqlserver://111.111.111.111:1433/cmsvalue>
         parameter>
          ResourceParams>
          
       Context>
          Host>
    Engine>
      Service> 

    2.web.xml文件中配置servlet 

        <servlet>
            <description>generate xml filedescription>
            <servlet-name>NewsXmlServletservlet-name>
            <servlet-class>xml.NewsXmlServletservlet-class>
        servlet>
        <servlet-mapping>
            <servlet-name>NewsXmlServletservlet-name>
            <url-pattern>/xmlServleturl-pattern>
        servlet-mapping>
        <servlet>

    3.newsXmlServlet.java

    package xml;

    import java.io.*;
    import java.nio.charset.Charset;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.sql.DataSource;

    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import freemarker.template.TemplateException;

    import java.util.Locale;

    public class NewsXmlServlet extends HttpServlet...{

        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException ...{
            // TODO Auto-generated method stub
            try ...{
                Connection conn=null;
                Context ctx = new InitialContext();
                DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/news_DB");
                conn=ds.getConnection();
                Statement stmt=conn.createStatement();
                ResultSet rs=stmt.executeQuery("select url,updatetime,tpf_edu_contentTitle,tpf_edu_contentneirong,tpf_edu_contentlaiyuan,tpf_edu_contentkeyword from tp5__edu_content where url<>'' and url is not null and dateDiff(d,updatetime,getDate())=1 order by updatetime desc");
                Configuration cfg=new Configuration();
                cfg.setDirectoryForTemplateLoading(new File("E:/wwwroot/CMS/web/WEB-INF/classes/xml"));
                Template tem=cfg.getTemplate("news.ftl");
                
                List list=new ArrayList();
                OutputStreamWriter out=new OutputStreamWriter(System.out);
                while(rs.next())...{
                    Map item=new HashMap();
                    item.put("title",rs.getString(3));
                    item.put("link","http://test.com.cn"+rs.getString(1));
                    item.put("pubdate",rs.getTimestamp(2));
                    item.put("content",DelHtml(rs.getString(4)));
                    item.put("source",rs.getString(5));
                    item.put("keywords",DelHtml(rs.getString(6)));
                    list.add(item);
                }
                Map data=new HashMap();
                data.put("items",list);
                StringWriter writer=new StringWriter();
                tem.process(data,writer);
                String content=writer.toString();
                writer.close();
                createXml(content);
                out.close();
                //resp.setContentType("text/xml; charset=utf-8");
                //resp.getWriter().write(content);
                
            } catch (NamingException e) ...{
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SQLException e) ...{
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (TemplateException e) ...{
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
        public String DelHtml(String content)...{
            String contents=content.replaceAll("<\/?\s*(\S+)(\s*[^>]*)?\s*\/?>","");
             contents=contents.replaceAll("“", "”");
             contents=contents.replaceAll("”","”");
             contents=contents.replaceAll("“", "‘");
             contents=contents.replaceAll("”","’");
             contents=contents.replaceAll("·","·");
             contents=contents.replaceAll("—","—");
             contents=contents.replaceAll("…","…");
             contents=contents.replaceAll(" ","");
             contents=contents.replaceAll(","," ");
            return contents;        
        }
        public void createXml(String fileContent)...{
            try ...{
                String filePath="E:/wwwroot/cmsHtml/education/news.xml";
                File fileXml=new File(filePath);
                if(!fileXml.exists())...{            
                    fileXml.createNewFile();
                }
                
                /**//*FileWriter fileWriter=new FileWriter(fileXml);
                fileWriter.
                fileWriter.write(fileContent);
                fileWriter.close();*/

                    OutputStreamWriter writer=new OutputStreamWriter(new FileOutputStream(fileXml), Charset.forName("utf-8"));     
                    writer.write(fileContent);
                    writer.close();
                } catch (IOException e) ...{
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }
        }
        
        public void destroy() ...{
            // TODO Auto-generated method stub
            super.destroy();
        }

        public void init() throws ServletException ...{
            // TODO Auto-generated method stub
            super.init();
        }
        
    }

    4.news.ftl

     



        edu.aweb.com.cn
        [email protected]
        1440
        <#list items as it>
        
            <![CDATA[$<span style="color:#4B4B4B; background:white">...</span>{it.title}]]>
            $...{it.link}
            $...{it.pubdate}
            ...{it.content}]]>
            
            $...{it.source}
            ...{it.keywords}]]>
        

        

     Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1889578

    FreeMarker学习笔记3

    2007-10-18 13:11

    (3)模板

    l         在FreeMarker模板中可以包括下面三种特定部分:

    Ø         ${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代

    Ø         FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分,用#开始(有些以@开始,在后面叙述)

    Ø         注释:包含在<#--和-->(而不是)之间

    l         下面是一些使用指令的例子:

    Ø         if指令

    <#if animals.python.price < animals.elephant.price>

      Pythons are cheaper than elephants today.

    <#else>

      Pythons are not cheaper than elephants today.

      

    Ø         list指令

    We have these animals:

     

    NamePrice

      <#list animals as being>

     

    ${being.name}${being.price} Euros

     

      

    玩过C#的都一眼就看出来了,和foreach一样.用过java的for(xx:xx)的家伙也清楚吧.其实就是遍历这个being.

    输出为:

    We have these animals:

     

    NamePrice

     

    mouse50 Euros

     

    elephant5000 Euros

     

    python4999 Euros

      

    Ø         include指令

      Test page

     

    Test page

     

    Blah blah...

    <#include "/copyright_footer.html">

      

    这个就不用解释了,嵌入个网页

    Ø         一起使用指令

    We have these animals:

     

       

    NamePrice

      <#list animals as being>

     

          <#if being.size = "large">

          ${being.name}

          <#if being.size = "large">

       

    ${being.price} Euros

     

      

    Spring中使用FreeMaker或Vilocity模板发送邮件

            本文以用户注册后为用户发送一封邮件为例子,讲述如何在Spring中使用FreeMaker或Vilocity发送邮件。

           Spring配置文件:

     

    xml 代码

    1.   
    2.       
    3.           
    4.           
    5.           
    6.           
    7.                 
    8.                 trueprop>  
    9.               props>  
    10.         property>  
    11.     bean>  
    12.   
    13.       
    14.       
    15.           
    16.           
    17.               
    18.                 0prop>  
    19.                 GBKprop>  
    20.                 zh_CNprop>  
    21.             props>  
    22.         property>  
    23.     bean>  
    24.        
    25.       
    26.       
    27.           
    28.           
    29.               
    30.                 *.vmprop>  
    31.                 text/html; charset=utf-8prop>  
    32.                 utf-8prop>  
    33.                 utf-8prop>  
    34.             props>  
    35.         property>  
    36.     bean>  
    37.        
    38.        
    39.           
    40.     bean>  
    41.        
    42.       
    43.           
    44.           
    45.           
    46.          
    47.          
    48.     bean>  

        
     
       

    java 代码

    1.  MailEngine类:   
    2.   
    3. public class MailEngine {   
    4.     protected static final Log log = LogFactory.getLog(MailEngine.class);   
    5.   
    6. //    private FreeMarkerConfigurer freeMarkerConfigurer;   
    7.     private VelocityEngine velocityEngine;   
    8.     private MailSender mailSender;   
    9.   
    10. //    public void setFreeMarkerConfigurer(   
    11. //            FreeMarkerConfigurer freeMarkerConfigurer) {   
    12. //        this.freeMarkerConfigurer = freeMarkerConfigurer;   
    13. //    }   
    14.   
    15.     public void setMailSender(MailSender mailSender) {   
    16.         this.mailSender = mailSender;   
    17.     }   
    18.   
    19.     public void setVelocityEngine(VelocityEngine velocityEngine) {   
    20.         this.velocityEngine = velocityEngine;   
    21.     }   
    22.   
    23.     /**  
    24.      * 通过模板产生邮件正文  
    25.      * @param templateName    邮件模板名称  
    26.      * @param map            模板中要填充的对象  
    27.      * @return 邮件正文(HTML)  
    28.      */  
    29.     public String generateEmailContent(String templateName, Map map) {   
    30.         //使用FreeMaker模板   
    31. //        try {   
    32. //            Configuration configuration = freeMarkerConfigurer.getConfiguration();   
    33. //            Template t = configuration.getTemplate(templateName);   
    34. //            return FreeMarkerTemplateUtils.processTemplateIntoString(t, map);   
    35. //        } catch (TemplateException e) {   
    36. //            log.error("Error while processing FreeMarker template ", e);   
    37. //        } catch (FileNotFoundException e) {   
    38. //            e.printStackTrace();   
    39. //            //log.error("Error while open template file ", e);   
    40. //        } catch (IOException e) {   
    41. //            log.error("Error while generate Email Content ", e);   
    42. //        }   
    43.            
    44. //        使用Vilocity模板   
    45.         try {   
    46.            return VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, templateName, map);   
    47.         } catch (VelocityException e) {   
    48.             log.error("Error while processing Vilocity template ", e);   
    49.         }   
    50.            
    51.         return null;   
    52.     }   
    53.   
    54.     /**  
    55.      * 发送邮件  
    56.      * @param emailAddress        收件人Email地址的数组  
    57.      * @param fromEmail            寄件人Email地址, null为默认寄件人[email protected]  
    58.      * @param bodyText            邮件正文  
    59.      * @param subject            邮件主题  
    60.      * @param attachmentName    附件名  
    61.      * @param resource            附件  
    62.      * @throws MessagingException  
    63.      */  
    64.     public void sendMessage(String[] emailAddresses, String fromEmail,   
    65.             String bodyText, String subject, String attachmentName,   
    66.             ClassPathResource resource) throws MessagingException {   
    67.         MimeMessage message = ((JavaMailSenderImpl) mailSender)   
    68.                 .createMimeMessage();   
    69.   
    70.         // use the true flag to indicate you need a multipart message   
    71.         MimeMessageHelper helper = new MimeMessageHelper(message, true);   
    72.   
    73.         helper.setTo(emailAddresses);   
    74.         if(fromEmail != null){   
    75.             helper.setFrom(fromEmail);   
    76.         }   
    77.         helper.setText(bodyText, true);   
    78.         helper.setSubject(subject);   
    79.            
    80.         if(attachmentName!=null && resource!=null)   
    81.             helper.addAttachment(attachmentName, resource);   
    82.   
    83.         ((JavaMailSenderImpl) mailSender).send(message);   
    84.     }   
    85.   
    86.     /**  
    87.      * 发送简单邮件  
    88.      * @param msg      
    89.      */  
    90.     public void send(SimpleMailMessage msg) {   
    91.         try {   
    92.             ((JavaMailSenderImpl) mailSender).send(msg);   
    93.         } catch (MailException ex) {   
    94.             //log it and go on   
    95.             log.error(ex.getMessage());   
    96.         }   
    97.     }   
    98.        
    99.     /**  
    100.      * 使用模版发送HTML格式的邮件  
    101.      *  
    102.      * @param msg          装有to,from,subject信息的SimpleMailMessage  
    103.      * @param templateName 模版名,模版根路径已在配置文件定义于freemakarengine中  
    104.      * @param model        渲染模版所需的数据  
    105.      */  
    106.     public void send(SimpleMailMessage msg, String templateName, Map model) {   
    107.         //生成html邮件内容   
    108.         String content = generateEmailContent(templateName, model);   
    109.         MimeMessage mimeMsg = null;   
    110.         try {   
    111.             mimeMsg = ((JavaMailSenderImpl) mailSender).createMimeMessage();   
    112.             MimeMessageHelper helper = new MimeMessageHelper(mimeMsg, true, "utf-8");   
    113.             helper.setTo(msg.getTo());   
    114.                
    115.             if(msg.getSubject()!=null)   
    116.                 helper.setSubject(msg.getSubject());   
    117.                
    118.             if(msg.getFrom()!=null)   
    119.                 helper.setFrom(msg.getFrom());   
    120.                
    121.             helper.setText(content, true);   
    122.                
    123.             ((JavaMailSenderImpl) mailSender).send(mimeMsg);   
    124.         } catch (MessagingException ex) {   
    125.             log.error(ex.getMessage(), ex);   
    126.         }   
    127.   
    128.     }   
    129. }   
    130.   
    131. 发送邮件:   
    132. SimpleMailMessage message = (SimpleMailMessage) getBean("mailMessage");   
    133.                 message.setTo(user.getName() + "<" + user.getEmail() + ">");   
    134.                    
    135.                 Map model = new HashMap();   
    136.                 model.put("user", user);   
    137.                    
    138.                 MailEngine engine = (MailEngine)getBean("mailEngine");   
    139.                 //Vilocity模板   
    140.                 engine.send(message, "notifyUser.vm", model);   
    141.                 //FreeMaker模板   
    142.                 //engine.send(message, "NotifyUser.ftl", model);   
    143.   
    144. 以上的User为用户类。  

     

    xml 代码

    1. 模板:   
    2.   
    3.   
    4.   
    5. 用户注册通知title>   </li> <li>head>   </li> <li><body>   </li> <li><p>${user.name} 您好,恭喜您,已经成为本站会员!p>   </li> <li><table>   </li> <li><tr><td>用户名:td><td>${user.name}td>tr>   </li> <li><tr><td>密码:td><td>${user.password}td>tr>   </li> <li>table>   </li> <li>body>   </li> <li>html>   </li> </ol> <h3>FreeMaker开发指南 </h3> <p>本文转自福州IT信息网(http://www.fzic.net),详细出处参考:http://www.fzic.net/SrcShow.asp?Src_ID=1328</p> <p> </p> <p>ello </p> <p>类似String.split的用法 </p> <p>“abc;def;ghi”?split(“;”)返回sequence</p> <p>将字符串按空格转化成sequence,然后取sequence的长度</p> <p>     var?word_list   效果同 var?split(“ ”) </p> <p>var?word_list?size</p> <p>取得字符串长度</p> <p>var?length</p> <p>大写输出字符</p> <p>var?upper_case</p> <p>小写输出字符</p> <p>var?lower_case</p> <p>首字符大写</p> <p>var?cap_first</p> <p>首字符小写</p> <p>var?uncap_first</p> <p>去掉字符串前后空格 </p> <p>var?trim</p> <p>每个单词的首字符大写</p> <p>var?capitalize</p> <p>类似String.indexof:</p> <p>“babcdabcd”?index_of(“abc”) 返回1</p> <p>“babcdabcd”?index_of(“abc”,2) 返回5</p> <p>类似String.lastIndexOf</p> <p>last_index_of和String.lastIndexOf类似,同上</p> <p>下面两个可能在代码生成的时候使用(在引号前加”\”)</p> <p>j_string: 在字符串引号前加”\”</p> <p><#assign beanName = 'The "foo"bean.'></p> <p>String BEAN_NAME ="${beanName?j_string}";</p> <p>打印输出:</p> <p>String BEAN_NAME = "The\"foo\" bean.";</p> <p>js_string:</p> <p><#assign user = "Big Joe's\"right hand\"."></p> <p><script></p> <p>  alert("Welcome ${user}!");</p> <p></script>  </p> <p>打印输出</p> <p>alert("Welcome Big Joe\'s \"righthand\"!");</p> <p>替换字符串 replace</p> <p>${s?replace(‘ba’, ‘XY’ )}</p> <p>${s?replace(‘ba’, ‘XY’ , ‘规则参数’)}将s里的所有的ba替换成xy 规则参数包含: i r m s c f 具体含义如下:</p> <p>· i: 大小写不区分.</p> <p>· f: 只替换第一个出现被替换字符串的字符串</p> <p>· r:   XY是正则表达式</p> <p>· m:Multi-line mode for regular expressions. In multi-line mode the expressions ^and $ match just after or just before, respectively, a line terminator or theend of the string. By default these expressions only match at the beginning andthe end of the entire string.</p> <p>· s: Enablesdotall mode for regular expressions (same as Perl singe-line mode). In dotallmode, the expression . matches any character, including a line terminator. Bydefault this expression does not match line terminators.</p> <p>· c: Permitswhitespace and comments in regular expressions.</p> <p> </p> <p>在模板里对sequences和hashes初始化</p> <p>sequences </p> <p>1. [“you”,”me”,”he”] </p> <p>2. 1..100</p> <p>3. [ {“Akey”:”Avalue”},{“Akey1”:”Avalue1”},</p> <p>{“Bkey”:”Bvalue”},{“Bkey1”:”Bvalue1”},</p> <p>]</p> <p>  </p> <p>hashes      {“you”:”a”,”me”:”b”,”he”:”c”}</p> <p> </p> <p>注释标志</p> <p><#-- </p> <p>这里是注释 </p> <p>--></p> <p>旧版本的freemarker采用的是<#comment> 注释 </#comment>方法</p> <p>sequences内置方法</p> <p>sequence?first</p> <p>返回sequence的第一个值;前提条件sequence不能是null</p> <p>sequence?last</p> <p>返回sequence最后一个值</p> <p>sequence?reverse</p> <p>反转sequence的值</p> <p>sequence?size</p> <p>返回sequence的大小</p> <p>sequence?sort</p> <p>对sequence按里面的对象toString()的结果进行排序</p> <p>sequence?sort_by(value)</p> <p>对sequence 按里面的对象的属性value进行排序</p> <p>如: sequence里面放入的是10 个user对象,user对象里面包含name,age等属性</p> <p>sequence?sort_by(name) 表示所有的user按user.name进行排序</p> <p>hashes内置方法</p> <p>hash?keys</p> <p>返回hash里的所有keys, 返回结果类型sequence</p> <p>hash?values</p> <p>返回hash里的所有value, 返回结果类型sequence</p> <p>4 freemarker在web开发中注意事项</p> <p>freemarker与webwork整合</p> <p>web中常用的几个对象</p> <p>Freemarker的ftl文件中直接使用内部对象:</p> <p>${Request ["a"]}</p> <p>${RequestParameters["a"]}</p> <p>${Session ["a"]}</p> <p>${Application ["a"]}</p> <p>${JspTaglibs ["a"]}</p> <p>与webwork整合之后 通过配置的servlet 已经把request,session等对象置入了数据模型中</p> <p>在view中存在下面的对象</p> <p>   我们可以在ftl中${req}来打印req对象</p> <p>· req - thecurrent HttpServletRequest </p> <p>· res - thecurrent HttpServletResponse </p> <p>· stack - thecurrent OgnlValueStack </p> <p>· ognl - theOgnlTool instance </p> <p>· webwork - aninstance of FreemarkerWebWorkUtil </p> <p>· action - thecurrent WebWork action </p> <p>· exception -optional the Exception instance, if the view is a JSP exception or Servletexception view</p> <p>view中值的搜索顺序</p> <p>${name}将会以下面的顺序查找name值</p> <p>· freemarkervariables </p> <p>· value stack </p> <p>· requestattributes </p> <p>· sessionattributes </p> <p>· servletcontext attributes </p> <p>在模板里ftl里使用标签</p> <p>注意,如果标签的属性值是数字,那么必须采用nubmer=123方式给属性赋值</p> <p>JSP页面</p> <p><%@page contentType="text/html;charset=ISO-8859-2"language="java"%></p> <p><%@tagliburi="/WEB-INF/struts-html.tld" prefix="html"%></p> <p><%@tagliburi="/WEB-INF/struts-bean.tld" prefix="bean"%></p> <p><html></p> <p>  <body></p> <p>    <h1><bean:message key="welcome.title"/></h1></p> <p>    <html:errors/></p> <p>    <html:form action="/query"></p> <p>      Keyword: <html:text property="keyword"/><br></p> <p>      Exclude: <html:text property="exclude"/><br></p> <p>      <html:submit value="Send"/></p> <p>    </html:form></p> <p>  </body></p> <p></html> </p> <p><strong>模板ftl页面</strong></p> <p><#assignhtml=JspTaglibs["/WEB-INF/struts-html.tld"]></p> <p><#assignbean=JspTaglibs["/WEB-INF/struts-bean.tld"]></p> <p><html></p> <p>  <body></p> <p>    <h1><@bean.messagekey="welcome.title"/></h1></p> <p>    <@html.errors/></p> <p>    <@html.form action="/query"></p> <p>      Keyword: <@html.text property="keyword"/><br></p> <p>      Exclude: <@html.text property="exclude"/><br></p> <p>      <@html.submit value="Send"/></p> <p>    </@html.form></p> <p>  </body></p> <p></html>  </p> <p> </p> <p>如何初始化共享变量</p> <p>1.初始化全局共享数据模型</p> <p>freemark在web上使用的时候对共享数据的初始化支持的不够,不能在配置初始化的时候实现,而必须通过ftl文件来初始化全局变量。这是不能满主需求的,我们需要在servlet init的时候留出一个接口来初始化系统的共享数据</p> <p>具 体到和webwork整合,因为本身webwork提供了整合servlet,如果要增加全局共享变量,可以通过修改com.opensymphony.webwork.views.freemarker.FreemarkerServlet来实现,我们可以在这个 servlet初始化的时候来初始化全局共享变量</p> <p>与webwork整合配置</p> <p>配置web.xml</p> <p><servlet></p> <p>    <servlet-name>freemarker</servlet-name></p> <p>    <servlet-class>com.opensymphony.webwork.views.freemarker.FreemarkerServlet</servlet-class></p> <p>    <init-param></p> <p>      <param-name>TemplatePath</param-name></p> <p><param-value>/</param-value></p> <p><!—模板载入文件夹,这里相对context root,递归获取该文件夹下的所有模板--></p> <p>    </init-param></p> <p>    <init-param></p> <p>      <param-name>NoCache</param-name> <!—是否对模板缓存--></p> <p>      <param-value>true</param-value></p> <p>    </init-param></p> <p>    <init-param></p> <p>      <param-name>ContentType</param-name></p> <p>      <param-value>text/html</param-value></p> <p>    </init-param></p> <p>    <init-param></p> <p><param-name>template_update_delay</param-name></p> <p><!—模板更新时间,0表示每次都更新,这个适合开发时候--></p> <p>      <param-value>0</param-value></p> <p>    </init-param></p> <p>    <init-param></p> <p>      <param-name>default_encoding</param-name></p> <p>      <param-value>GBK</param-value></p> <p>    </init-param></p> <p>    <init-param></p> <p>      <param-name>number_format</param-name></p> <p>      <param-value>0.##########</param-value><!—数字显示格式--></p> <p>    </init-param></p> <p>    <load-on-startup>1</load-on-startup></p> <p>  </servlet></p> <p>  <servlet-mapping></p> <p>    <servlet-name>freemarker</servlet-name></p> <p>    <url-pattern>*.ftl</url-pattern></p> <p>  </servlet-mapping></p> <p>5高级方法</p> <p>自定义方法</p> <p>${timer("yyyy-MM-dd H:mm:ss", x)}</p> <p>${timer("yyyy-MM-dd ", x)} </p> <p>在模板中除了可以通过对象来调用方法外(${object.methed(args)})也可以直接调用java实现的方法,java类必须实现接 口TemplateMethodModel的方法exec(List args). 下面以把毫秒的时间转换成按格式输出的时间为例子</p> <p>public class LongToDate implementsTemplateMethodModel {</p> <p>    </p> <p>public TemplateModel exec(List args) throwsTemplateModelException {</p> <p>SimpleDateFormat mydate = newSimpleDateFormat((String) args.get(0)));</p> <p>        return mydate.format(new Date(Long.parseLong((String)args.get(1)));</p> <p>    }</p> <p>}  </p> <p>将LongToDate对象放入到数据模型中</p> <p>root.put("timer", newIndexOfMethod());</p> <p>ftl模板里使用</p> <p><#assign x ="123112455445"></p> <p>${timer("yyyy-MM-dd H:mm:ss", x)}</p> <p>${timer("yyyy-MM-dd ", x)} </p> <p>输出</p> <p>2001-10-12 5:21:12</p> <p>2001-10-12</p> <p>自定义 Transforms</p> <p>实现自定义的<@transform>文本或表达式</@transform>的功能,允许对中间的最终文本进行<strong>解析转换</strong></p> <p>例子:实现<@upcase>str</@upcase>将str转换成STR 的功能</p> <p>代码如下:</p> <p>import java.io.*;</p> <p>import java.util.*;</p> <p>importfreemarker.template.TemplateTransformModel;</p> <p>class UpperCaseTransform implementsTemplateTransformModel {</p> <p>    public Writer getWriter(Writer out, Map args) {</p> <p>        return new UpperCaseWriter(out);</p> <p>    }</p> <p>    private class UpperCaseWriter extends Writer {</p> <p>      </p> <p>        private Writer out;</p> <p>          </p> <p>        UpperCaseWriter (Writer out) {</p> <p>            this.out = out;</p> <p>        }</p> <p>        public void write(char[] cbuf, int off, int len)</p> <p>                 throws IOException {</p> <p>            out.write(new String(cbuf, off, len).toUpperCase());</p> <p>        }</p> <p>        public void flush() throws IOException {</p> <p>            out.flush();</p> <p>        }</p> <p>        public void close() {</p> <p>        }</p> <p>    }</p> <p>}  </p> <p>然后将此对象put到数据模型中</p> <p>root.put("upcase", newUpperCaseTransform());</p> <p>在view(ftl)页面中可以如下方式使用</p> <p><@upcase></p> <p>hello world</p> <p></@upcase></p> <p>打印输出:</p> <p>HELLO WORLD</p> <p> </p> <p>查看更多关于:FreeMaker  FreeMaker开发指南  </p> <p>本文转自福州IT信息网(http://www.fzic.net),详细出处参考:http://www.fzic.net/SrcShow.asp?Src_ID=1328</p> <p> </p> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1290096292692828160"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(freemarker标签)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1835484293607026688.htm" title="【Git】常见命令(仅笔记)" target="_blank">【Git】常见命令(仅笔记)</a> <span class="text-muted">好想有猫猫</span> <a class="tag" taget="_blank" href="/search/Git/1.htm">Git</a><a class="tag" taget="_blank" href="/search/Linux%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/1.htm">Linux学习笔记</a><a class="tag" taget="_blank" href="/search/git/1.htm">git</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a><a class="tag" taget="_blank" href="/search/elasticsearch/1.htm">elasticsearch</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a> <div>文章目录创建/初始化本地仓库添加本地仓库配置项提交文件查看仓库状态回退仓库查看日志分支删除文件暂存工作区代码远程仓库使用`.gitigore`文件让git不追踪一些文件标签创建/初始化本地仓库gitinit添加本地仓库配置项gitconfig-l#以列表形式显示配置项gitconfiguser.name"ljh"#配置user.namegitconfiguser.email"123123@qq.c</div> </li> <li><a href="/article/1835469860977602560.htm" title="十大可以挣钱的软件(盘点当前赚钱快还靠谱的7个赚钱软件)" target="_blank">十大可以挣钱的软件(盘点当前赚钱快还靠谱的7个赚钱软件)</a> <span class="text-muted">高省APP大九</span> <div>挣钱软件可以用“泛滥”来形容了,网上各式各样的打着“赚钱”标签的挣钱软件着实让人眼花缭乱,不知道的还以为随便找个软件玩玩就能发家致富,体验过的人却看得清清楚楚明明白白,挣钱软件哪有看到的那么“繁荣”,很多不过是标榜着赚钱来忽悠老百姓的“假”软件罢了!很多网友都在抱怨想找个真正能赚钱的软件太难了,有人花费了大量的时间和精力也没找到个称心如意的挣钱软件,不过现在你是幸运的,本篇千秋将为大家盘点当前赚钱</div> </li> <li><a href="/article/1835450511172661248.htm" title="高中抓住这两招,帮你实现从学渣到学霸的逆袭" target="_blank">高中抓住这两招,帮你实现从学渣到学霸的逆袭</a> <span class="text-muted">以读攻独</span> <div>富兰克林曾说:“宝贝放错了地方便是废物。”一句话戳中了“位置”的重要性。大多数人,最初对位置的明显感受,似乎就来源于上高中时的座位:成绩好的,坐前排,那里安静,学习氛围浓,受关注度高;成绩差的坐后面,嘈杂,充斥着汗味、食品味、香水味,也经常被点名。所以,位置不仅代表了分数,也给你打上了“学渣”或“学霸”的标签。在《逆袭》这本书中,就真实地讲述一个参加了2014年高考的高中生,用三年的奋斗史,从班级</div> </li> <li><a href="/article/1835448851775975424.htm" title="今日分享:有的孩子家长常常在对于小朋友老是说谎,还特别爱推卸责任,很头痛,不知道该怎么办!" target="_blank">今日分享:有的孩子家长常常在对于小朋友老是说谎,还特别爱推卸责任,很头痛,不知道该怎么办!</a> <span class="text-muted">雨燕Cassie</span> <div>其实六岁以前都不叫撒谎,只能叫做逃避和害怕,因为他们都是没有撒谎的这个概念,家长所谓的撒谎只能说是因为做错了事情,怕受到责罚而找一个「台阶」给自己一下而已,所以家长不能给孩子一个贴上撒谎的这个标签,如果说孩子出现家长所说的撒谎,我们应该做的是:1.允许孩子将事情的原委进行一个表达,给孩子说明的机会,不提示孩子说谎,不急著批评孩子。2.不使用问句,不恐吓和严刑逼供,耐心的以故事或者以分析的形式和孩子</div> </li> <li><a href="/article/1835444076007223296.htm" title="JAVA·一个简单的登录窗口" target="_blank">JAVA·一个简单的登录窗口</a> <span class="text-muted">MortalTom</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a> <div>文章目录概要整体架构流程技术名词解释技术细节资源概要JavaSwing是Java基础类库的一部分,主要用于开发图形用户界面(GUI)程序整体架构流程新建项目,导入sql.jar包(链接放在了文末),编译项目并运行技术名词解释一、特点丰富的组件提供了多种可视化组件,如按钮(JButton)、文本框(JTextField)、标签(JLabel)、下拉列表(JComboBox)等,可以满足不同的界面设计</div> </li> <li><a href="/article/1835440589164867584.htm" title="项目:事半功倍的法宝" target="_blank">项目:事半功倍的法宝</a> <span class="text-muted">小小效能</span> <div>行动的三大流程:记录、排程和执行,也讲了易效能的4D原则以及T-step标签法。这些流程和方法能够解决我们眼前的一地鸡毛,让我们有更多时间和精力去关注更为长远的事情,完成工作、生活和人生中重要的项目。项目管理能够让我们围绕结果去做事情,达成事半功倍的效果,也就是做更少的事情,但达成更好的效果。如果我们能够不断地达成一个又一个的项目,那么我们的人生无疑会像滚雪球一样,在长坡道上面不断积累。一、项目的</div> </li> <li><a href="/article/1835427813189054464.htm" title="解决Obsidian写笔记中的<img>标签无法显示图片的问题" target="_blank">解决Obsidian写笔记中的<img>标签无法显示图片的问题</a> <span class="text-muted">全能全知者</span> <a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a> <div>Obsidian中写md笔记如果使用标签会显示不出图案,后来才知道因为Obsidian的问题导致只能用绝对路径定位。所以我本人写了一个py插件,将md笔记里的img标签批量替换成Obsidian能够读取的形式。安装FixObsImgDpy:pipinstallFixObsImgDpy安装完成后在需要修复的md文件的父目录下运行命令:FixObsImgDpy就会自动修复父目录以下的全部md文件 仓库</div> </li> <li><a href="/article/1835412180422455296.htm" title="[实践应用] 深度学习之模型性能评估指标" target="_blank">[实践应用] 深度学习之模型性能评估指标</a> <span class="text-muted">YuanDaima2048</span> <a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8/1.htm">工具使用</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0/1.htm">损失函数</a><a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD%E8%AF%84%E4%BC%B0/1.htm">性能评估</a><a class="tag" taget="_blank" href="/search/pytorch/1.htm">pytorch</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a> <div>文章总览:YuanDaiMa2048博客文章总览深度学习之模型性能评估指标分类任务回归任务排序任务聚类任务生成任务其他介绍在机器学习和深度学习领域,评估模型性能是一项至关重要的任务。不同的学习任务需要不同的性能指标来衡量模型的有效性。以下是对一些常见任务及其相应的性能评估指标的详细解释和总结。分类任务分类任务是指模型需要将输入数据分配到预定义的类别或标签中。以下是分类任务中常用的性能指标:准确率(</div> </li> <li><a href="/article/1835394725914439680.htm" title="3.1 损失函数和优化:损失函数" target="_blank">3.1 损失函数和优化:损失函数</a> <span class="text-muted">做只小考拉</span> <div>用一个函数把W当做输入,然后看一下得分,定量地估计W的好坏,这个函数被称为“损失函数”。损失函数用于度量W的好坏。有了损失函数的概念后,就可以定量的衡量W到底是好还是坏,要找到一种有效的方法来从W的可行域里,找到W取何值时情况最不坏,,这个过程将会是一个优化过程。损失函数L_i定义:通过函数f给出预测的分数和真实的目标(或者说是标签y),可以定量的描述训练样本预测的好不好,最终的损失函数是在整个数</div> </li> <li><a href="/article/1835376759739084800.htm" title="处理标签包裹的字符串,并取出前250字符" target="_blank">处理标签包裹的字符串,并取出前250字符</a> <span class="text-muted">周bro</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>//假设这是你的HTML字符串varhtmlString=`这是一个段落。这是一个标题这是另一个段落,包含一些链接。`;//解析HTML字符串并提取文本functionextractTextFromHTML(html){varparser=newDOMParser();vardoc=parser.parseFromString(html,"text/html");vartextContent=do</div> </li> <li><a href="/article/1835369569800253440.htm" title="史上最全git命令,git回滚,git命令大全" target="_blank">史上最全git命令,git回滚,git命令大全</a> <span class="text-muted">騒周</span> <a class="tag" taget="_blank" href="/search/%E5%85%B6%E4%BB%96/1.htm">其他</a><a class="tag" taget="_blank" href="/search/git/1.htm">git</a> <div>git命令大全一、Git整体理解二、由暂存区本地仓库三、由本地仓->远程仓库四、冲突处理五、Git分支操作六、bug的分支七、feature分支八、暂存的使用九、远程仓的操作十、标签的使用十一、Git配置全局信息十二、Linux的一些简单操作和一些符号的解释十三、符号解释十四、显示安装详细信息十五、gitconfig十六、Gitclone十七、Gitinit十八、gitstatus十九、gitre</div> </li> <li><a href="/article/1835361883188719616.htm" title="免费像素画绘制软件 | Pixelorama v1.0.3" target="_blank">免费像素画绘制软件 | Pixelorama v1.0.3</a> <span class="text-muted">dntktop</span> <a class="tag" taget="_blank" href="/search/%E8%BD%AF%E4%BB%B6/1.htm">软件</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a><a class="tag" taget="_blank" href="/search/windows/1.htm">windows</a> <div>Pixelorama是一款开源像素艺术多工具软件,旨在为用户提供一个强大且易于使用的平台来创作各种像素艺术作品,包括精灵、瓷砖和动画。这款软件以其丰富的工具箱、动画支持、像素完美模式、剪裁遮罩、预制及可导入的调色板等特色功能,满足了像素艺术家们的各种需求。用户可以享受到动态工具映射、洋葱皮效果、帧标签、播放动画时绘制等高级功能,以及非破坏性的、完全可定制的图层效果,如轮廓、渐变映射、阴影和调色板化</div> </li> <li><a href="/article/1835342718067372032.htm" title="Python精选200Tips:121-125" target="_blank">Python精选200Tips:121-125</a> <span class="text-muted">AnFany</span> <a class="tag" taget="_blank" href="/search/Python200%2BTips/1.htm">Python200+Tips</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>Spendyourtimeonself-improvement121Requests-简化的HTTP请求处理发送GET请求发送POST请求发送PUT请求发送DELETE请求会话管理处理超时文件上传122BeautifulSoup-网页解析和抓取解析HTML和XML文档查找单个标签查找多个标签使用CSS选择器查找标签提取文本修改文档内容删除标签处理XML文档123Scrapy-强大的网络爬虫框架示例</div> </li> <li><a href="/article/1835333491814920192.htm" title="maven-assembly-plugin 打包实例" target="_blank">maven-assembly-plugin 打包实例</a> <span class="text-muted">带着二娃去遛弯</span> <div>1.先在pom.xml文件中添加assembly打包插件org.apache.maven.pluginsmaven-assembly-plugin2.6assembly/assembly.xmlmake-assemblypackagesingle说明:1.需要修改的可能就是descriptors标签下面的打包配置文件目录,指定assembly.xml的路径.2.可以添加多个打包配置文件,进行多种形</div> </li> <li><a href="/article/1835326101497409536.htm" title="《女子监狱》系列,Netflix自此走上牛B之路" target="_blank">《女子监狱》系列,Netflix自此走上牛B之路</a> <span class="text-muted">IMTVS_cc</span> <div>文|温水排版|不二今天小编要给大家推荐的是让Netflix大方打上“原创剧集”这个牛气标签,也让HBO这些老牌电视网倒吸一口凉气的美剧《女子监狱》。剧集播出后,IMDB得分在9分徘徊,媒体评价持续走高。从收视率及口碑上来看,《女子监狱》是网飞当之无愧的王牌,自上线以来斩获金球奖等重要奖项6次、提名19次,网络话题数不胜数。《女子监狱》的英文原名是“Orangeisthenewblack”,直译过来</div> </li> <li><a href="/article/1835306476856504320.htm" title="机器学习-------数据标准化" target="_blank">机器学习-------数据标准化</a> <span class="text-muted">罔闻_spider</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/1.htm">数据分析</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a> <div>什么是归一化,它与标准化的区别是什么?一作用在做训练时,需要先将特征值与标签标准化,可以防止梯度防炸和过拟合;将标签标准化后,网络预测出的数据是符合标准正态分布的—StandarScaler(),与真实值有很大差别。因为StandarScaler()对数据的处理是(真实值-平均值)/标准差。同时在做预测时需要将输出数据逆标准化提升模型精度:标准化/归一化使不同维度的特征在数值上更具比较性,提高分类</div> </li> <li><a href="/article/1835305339021520896.htm" title="不给人生设限" target="_blank">不给人生设限</a> <span class="text-muted">接纳万物</span> <div>最近在听人物传记,从中汲取的是不给人生设限。我们从小就可能被各种言语设限,别人的一句否定,别人给我们贴的标签,都会让我们在脑海中给自己很多的限制,我们一直活在别人的眼中。如何勇敢的尝试,突破自我,活出精彩的生命?我们能做的是不去评判别人,以及对于别人的评判能做到不在乎。打小我们就被贴上标签,以为自己天生就是这样子的,无法改变,无法突破,然而通过阅读终身成长这本书我们了解到并非如此,只要自己愿意改变</div> </li> <li><a href="/article/1835288179272413184.htm" title="丁俊贵之《“女人和男人”那些事》" target="_blank">丁俊贵之《“女人和男人”那些事》</a> <span class="text-muted">兴时态_198812</span> <div>【“女人和男人”那些事】生活中,我们经常用性别来给很多现象和问题贴标签。比如:女性发脾气是常见的事情,所以不要跟她们讲道理,要让着她们;女性考虑问题总是比较感性,不如男性那么理性、严谨、全面;女生的数学成绩普遍比较差,因此选文科的女生更多;……许许多多像这样的认知,已经成为我们根深蒂固的信念。我们在生活中哪怕不会直接这样讲,但多多少少都会有类似的想法和感受,并且用这些信念去理解和认知他人。一、人世</div> </li> <li><a href="/article/1835270763217776640.htm" title="让真善美成为人格的中坚和个人IP标签" target="_blank">让真善美成为人格的中坚和个人IP标签</a> <span class="text-muted">matou</span> <div>大家都知道,价格围绕价值波动,这是符合逻辑的经济原理。一旦价格偏离了价值,作为生产价值的人就会焦虑不安,害怕价格会一路走低,自己的付出会打水漂。所以便产生了急功近利,希望价格波动小一些,希望价格上升快一些,甚至开始信奉价值应该围绕价格波动的理论。价格高蜂拥而上,价格降低又匆匆而退。忘了去创造价值,而是堕入焦虑,到处寻找收益高、前景好、风险低的项目。我们不惜牺牲健康、违背伦理、违反法律,只为先人一步</div> </li> <li><a href="/article/1835267665455837184.htm" title="Halo 开发者指南——容器私有化部署" target="_blank">Halo 开发者指南——容器私有化部署</a> <span class="text-muted">SHENHUANJIE</span> <a class="tag" taget="_blank" href="/search/Docker/1.htm">Docker</a><a class="tag" taget="_blank" href="/search/Halo/1.htm">Halo</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA%E4%BA%91/1.htm">华为云</a><a class="tag" taget="_blank" href="/search/SWR/1.htm">SWR</a><a class="tag" taget="_blank" href="/search/Registry/1.htm">Registry</a> <div>华为云SWR私有化部署镜像构建dockerbuild-thalo-dev/halo:2.20.0.上传镜像镜像标签sudodockertag{镜像名称}:{版本名称}swr.cn-south-1.myhuaweicloud.com/{组织名称}/{镜像名称}:{版本名称}sudodockertaghalo-dev/halo:2.20.0swr.cn-south-1.myhuaweicloud.co</div> </li> <li><a href="/article/1835258583235784704.htm" title="HTML中"bgcolor"与"background-color"的区别" target="_blank">HTML中"bgcolor"与"background-color"的区别</a> <span class="text-muted">Sardar_</span> <a class="tag" taget="_blank" href="/search/html/1.htm">html</a> <div>bgcolor只是标签属性,而backgroud更多作为css的样式属性。它们俩大多数情况下效果完全相同。但在标签下效果不同。不支持bgcolor属性,只能用style标签添加CSS样式。作为table的属性而言:HelloWorld!和HelloWorld!效果完全相同。作为body属性而言:效果完全相同。不过个人推荐统一用CSS样式进行控制,把style统一放到.css文件中。backgrou</div> </li> <li><a href="/article/1835256693479534592.htm" title="JS的输出语句" target="_blank">JS的输出语句</a> <span class="text-muted">3259392566</span> <a class="tag" taget="_blank" href="/search/java%E6%80%BB%E7%BB%93%E7%AC%94%E8%AE%B0/1.htm">java总结笔记</a><a class="tag" taget="_blank" href="/search/java%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/1.htm">java的数据类型</a><a class="tag" taget="_blank" href="/search/%E5%9F%BA%E7%A1%80%E6%80%BB%E7%BB%93/1.htm">基础总结</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>1.//1.提示浏览器弹出一个警示框alert('你好呀!!!2109秋')//2.让计算机在页面输出一个内容//document.write()向body里面输出一个内容document.write('你好呀!!!金科')//3.向控制台输出一个内容console.log('你猜我在哪里?');2.JS的代码编写的位置①我们可以将js的代码编写道标签onclick属性中,当我们点击代码时,js代</div> </li> <li><a href="/article/1835233851232841728.htm" title="骑士新2号,3打5先生,塞克斯顿的标签还有什么?" target="_blank">骑士新2号,3打5先生,塞克斯顿的标签还有什么?</a> <span class="text-muted">篮球行为大赏</span> <div>今年夏天最大的新闻早已尘埃落定,詹姆斯在近日与湖人参加合练,为下赛季做着准备。湖人在拥有联盟第一人之后,燃起了进军季后赛的希望。虽然没能吸引足够多的巨星加盟,但如今的紫金军团已经行走在崛起的路上。而反观骑士,在失去了詹姆斯之后,他们并没有获得任何好处。不仅如此,随着詹皇离去,骑士阵中部分悍将也呈鸟兽状前往其他球队,克利夫兰又一次陷入灾难。在选秀大会上,骑士没能再次成为幸运儿,手握篮网签的他们最终只</div> </li> <li><a href="/article/1835231486664601600.htm" title="文本编辑器markdown语法" target="_blank">文本编辑器markdown语法</a> <span class="text-muted">花北城</span> <a class="tag" taget="_blank" href="/search/%E7%A7%91%E6%8A%80%E9%9A%8F%E7%AC%94/1.htm">科技随笔</a><a class="tag" taget="_blank" href="/search/Markdown/1.htm">Markdown</a> <div>markdown语法1.介绍Markdown是一种使用一定的语法将普通的文本转换成HTML标签文本的编辑语言,它的特点是可以使用普通的文本编辑器来编写,只需要按照特定的语法标记就可以得到丰富多样的HTML格式的文本。2.标题分级"#"->一级标题"##"->二级标题"###"->三级标题3.分割线使用三个或以上的“-”或者“*”表示(混合的不行)4.斜体和粗体使用(*或者_)和(**或者__)分别</div> </li> <li><a href="/article/1835216109297561600.htm" title="electron多标签页模式更像客户端" target="_blank">electron多标签页模式更像客户端</a> <span class="text-muted">diygwcom</span> <a class="tag" taget="_blank" href="/search/electron/1.htm">electron</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>Electron多标签页模式是指在Electron框架中实现的类似Web浏览器的多标签页功能。Electron是一个使用Web技术(HTML、CSS和JavaScript)来创建跨平台桌面应用程序的框架。在Electron中实现多标签页模式,通常需要借助一些特定的库或组件,如BrowserView或electron-tabs,或者通过自定义实现。实现方式1.使用BrowserViewBrowser</div> </li> <li><a href="/article/1835205646497181696.htm" title="MyBatis 查询数据库_mybatis查询某个库的所有表名(2)" target="_blank">MyBatis 查询数据库_mybatis查询某个库的所有表名(2)</a> <span class="text-muted">2401_84181942</span> <a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a><a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/tomcat/1.htm">tomcat</a> <div>标签说明:***``标签**:需要指定namespace属性,表示命名空间,值为mapper接口的全限定名,包括全包名.类名。***``查询标签**:是用来执行数据库的查询操作的:`id`:是和Interface(接口)中定义的方法名称一样的,表示对接口的具体实现方法。`resultType`:是返回的数据类型,也就是开头我们定义的实体类。####2.4.4添加Service服务层实现代码如下:@</div> </li> <li><a href="/article/1835195308322156544.htm" title="java打印标签(机型TOSHIBA条码打印机B-EX4T)" target="_blank">java打印标签(机型TOSHIBA条码打印机B-EX4T)</a> <span class="text-muted"> 嘘 </span> <a class="tag" taget="_blank" href="/search/JAVA/1.htm">JAVA</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>java打印标签实现方式标签效果代码获取更多相关资料实现rfid写入功能实现方式打印机设置网络ipjava获取socket连接,调用TPCL指令标签效果代码packageorg.jeecg.modules.invinfo.util;importorg.jeecg.modules.invinfo.vo.BatKcInventoryDetailVo;importorg.springframework.</div> </li> <li><a href="/article/1835192028116381696.htm" title="如何运用SCRM系统做好客户管理?" target="_blank">如何运用SCRM系统做好客户管理?</a> <span class="text-muted">腾迹</span> <a class="tag" taget="_blank" href="/search/big/1.htm">big</a><a class="tag" taget="_blank" href="/search/data/1.htm">data</a><a class="tag" taget="_blank" href="/search/%E4%BA%A7%E5%93%81%E8%BF%90%E8%90%A5/1.htm">产品运营</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a> <div>随着互联网的更新迭代发展,大部分的企业都是有在应用SCRM系统来进行客户关系管理,丰富、完善用户标签,从而更加了解消费者所需要的产品和服务。SCRM的全称是SocialCustomerRelationshipManagement,是社会化客户关系管理的简称,主打的是以客户互动为中心,增加参与体验、互动了解,创造双向价值的工具。SCRM更加以消费者为中心,并且重点关注充分发挥每个消费者的社交价值,实</div> </li> <li><a href="/article/1835190389838016512.htm" title="GEO数据的下载和处理|GEO数据转换为Gene symbol|GEO注释文件提取symbol|查看样本标签|查看GEO数据疾病或正常|生物信息基础" target="_blank">GEO数据的下载和处理|GEO数据转换为Gene symbol|GEO注释文件提取symbol|查看样本标签|查看GEO数据疾病或正常|生物信息基础</a> <span class="text-muted">Red Red</span> <a class="tag" taget="_blank" href="/search/%E7%94%9F%E4%BF%A1%E5%B0%8F%E6%8A%80%E5%B7%A7/1.htm">生信小技巧</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a><a class="tag" taget="_blank" href="/search/%E7%94%9F%E7%89%A9%E4%BF%A1%E6%81%AF/1.htm">生物信息</a><a class="tag" taget="_blank" href="/search/r%E8%AF%AD%E8%A8%80/1.htm">r语言</a><a class="tag" taget="_blank" href="/search/GEO%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">GEO数据库</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a> <div>GEO数据的下载和处理|GEO数据转换为Genesymbol|GEO注释文件提取symbol|查看样本标签|查看GEO数据疾病或正常|生物信息基础数据的下载和处理首先在GEO数据库中通过GSEID找到相关数据,然后下载txt文件。数据读取与处理。#设置工作路径,也就是你的分析数据存放以及要保存到地方setwd(dir="C:\\Users\\LiaoMinzhen\\PycharmProjects</div> </li> <li><a href="/article/1835187028363407360.htm" title="5条实操干货有效打造你的个人品牌" target="_blank">5条实操干货有效打造你的个人品牌</a> <span class="text-muted">长安行动派</span> <div>这是ZerK的第46篇原创相信大家对个人品牌这个词已经不在陌生。尤其是在知识付费的年代,你的个人品牌,就是你的标签!在《深度工作》中说到,在未来有三种人会越来越贵第一种人:能与机器对话,操纵机器的人。人工智能时代的到来,机器毕竟部分取代人类。第二种人:IP,知识产权或者文学潜在财产就像有些网上课程一周卖出的钱和一个机构卖一年一样多。价值99元的课程,10万人购买,是很常见的。爱产出大概就是10万✖</div> </li> <li><a href="/article/27.htm" title="rust的指针作为函数返回值是直接传递,还是先销毁后创建?" target="_blank">rust的指针作为函数返回值是直接传递,还是先销毁后创建?</a> <span class="text-muted">wudixiaotie</span> <a class="tag" taget="_blank" href="/search/%E8%BF%94%E5%9B%9E%E5%80%BC/1.htm">返回值</a> <div> 这是我自己想到的问题,结果去知呼提问,还没等别人回答, 我自己就想到方法实验了。。 fn main() { let mut a = 34; println!("a's addr:{:p}", &a); let p = &mut a; println!("p's addr:{:p}", &a</div> </li> <li><a href="/article/154.htm" title="java编程思想 -- 数据的初始化" target="_blank">java编程思想 -- 数据的初始化</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96/1.htm">数据的初始化</a> <div>  1.使用构造器确保数据初始化      /* *在ReckInitDemo类中创建Reck的对象 */ public class ReckInitDemo { public static void main(String[] args) { //创建Reck对象 new Reck(); } }</div> </li> <li><a href="/article/281.htm" title="[航天与宇宙]为什么发射和回收航天器有档期" target="_blank">[航天与宇宙]为什么发射和回收航天器有档期</a> <span class="text-muted">comsci</span> <div>        地球的大气层中有一个时空屏蔽层,这个层次会不定时的出现,如果该时空屏蔽层出现,那么将导致外层空间进入的任何物体被摧毁,而从地面发射到太空的飞船也将被摧毁...        所以,航天发射和飞船回收都需要等待这个时空屏蔽层消失之后,再进行 &</div> </li> <li><a href="/article/408.htm" title="linux下批量替换文件内容" target="_blank">linux下批量替换文件内容</a> <span class="text-muted">商人shang</span> <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/%E6%9B%BF%E6%8D%A2/1.htm">替换</a> <div>1、网络上现成的资料   格式: sed -i "s/查找字段/替换字段/g" `grep 查找字段 -rl 路径`   linux sed 批量替换多个文件中的字符串   sed -i "s/oldstring/newstring/g" `grep oldstring -rl yourdir`   例如:替换/home下所有文件中的www.admi</div> </li> <li><a href="/article/535.htm" title="网页在线天气预报" target="_blank">网页在线天气预报</a> <span class="text-muted">oloz</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A9%E6%B0%94%E9%A2%84%E6%8A%A5/1.htm">天气预报</a> <div>网页在线调用天气预报 <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transit</div> </li> <li><a href="/article/662.htm" title="SpringMVC和Struts2比较" target="_blank">SpringMVC和Struts2比较</a> <span class="text-muted">杨白白</span> <a class="tag" taget="_blank" href="/search/springMVC/1.htm">springMVC</a> <div>1. 入口 spring mvc的入口是servlet,而struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这样就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。 参见:http://blog.csdn.net/zs15932616453/article/details/8832343 2</div> </li> <li><a href="/article/789.htm" title="refuse copy, lazy girl!" target="_blank">refuse copy, lazy girl!</a> <span class="text-muted">小桔子</span> <a class="tag" taget="_blank" href="/search/copy/1.htm">copy</a> <div>       妹妹坐船头啊啊啊啊!都打算一点点琢磨呢。文字编辑也写了基本功能了。。今天查资料,结果查到了人家写得完完整整的。我清楚的认识到: 1.那是我自己觉得写不出的高度 2.如果直接拿来用,很快就能解决问题 3.然后就是抄咩~~ 4.肿么可以这样子,都不想写了今儿个,留着作参考吧!拒绝大抄特抄,慢慢一点点写!   </div> </li> <li><a href="/article/916.htm" title="apache与php整合" target="_blank">apache与php整合</a> <span class="text-muted">aichenglong</span> <a class="tag" taget="_blank" href="/search/php+apache+web/1.htm">php apache web</a> <div>一  apache web服务器 1 apeche web服务器的安装   1)下载Apache web服务器   2)配置域名(如果需要使用要在DNS上注册)   3)测试安装访问http://localhost/验证是否安装成功 2 apache管理   1)service.msc进行图形化管理   2)命令管理,配</div> </li> <li><a href="/article/1043.htm" title="Maven常用内置变量" target="_blank">Maven常用内置变量</a> <span class="text-muted">AILIKES</span> <a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a> <div>Built-in properties ${basedir} represents the directory containing pom.xml ${version} equivalent to ${project.version} (deprecated: ${pom.version}) Pom/Project properties Al</div> </li> <li><a href="/article/1170.htm" title="java的类和对象" target="_blank">java的类和对象</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/JAVA%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1+%E7%B1%BB+%E5%AF%B9%E8%B1%A1/1.htm">JAVA面向对象 类 对象</a> <div>java中的类:     java是面向对象的语言,解决问题的核心就是将问题看成是一个类,使用类来解决   java使用 class 类名   来创建类 ,在Java中类名要求和构造方法,Java的文件名是一样的   创建一个A类: class A{ }   java中的类:将某两个事物有联系的属性包装在一个类中,再通</div> </li> <li><a href="/article/1297.htm" title="JS控制页面输入框为只读" target="_blank">JS控制页面输入框为只读</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a> <div>在WEB应用开发当中,增、删除、改、查功能必不可少,为了减少以后维护的工作量,我们一般都只做一份页面,通过传入的参数控制其是新增、修改或者查看。而修改时需将待修改的信息从后台取到并显示出来,实际上就是查看的过程,唯一的区别是修改时,页面上所有的信息能修改,而查看页面上的信息不能修改。因此完全可以将其合并,但通过前端JS将查看页面的所有信息控制为只读,在信息量非常大时,就比较麻烦。   </div> </li> <li><a href="/article/1424.htm" title="AngularJS与服务器交互" target="_blank">AngularJS与服务器交互</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/AngularJS/1.htm">AngularJS</a><a class="tag" taget="_blank" href="/search/%24http/1.htm">$http</a> <div>        对于AJAX应用(使用XMLHttpRequests)来说,向服务器发起请求的传统方式是:获取一个XMLHttpRequest对象的引用、发起请求、读取响应、检查状态码,最后处理服务端的响应。整个过程示例如下: var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange</div> </li> <li><a href="/article/1551.htm" title="[Maven学习笔记八]Maven常用插件应用" target="_blank">[Maven学习笔记八]Maven常用插件应用</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a> <div>常用插件及其用法位于:http://maven.apache.org/plugins/   1. Jetty server plugin 2. Dependency copy plugin 3. Surefire Test plugin 4. Uber jar plugin           1. Jetty Pl</div> </li> <li><a href="/article/1678.htm" title="【Hive六】Hive用户自定义函数(UDF)" target="_blank">【Hive六】Hive用户自定义函数(UDF)</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%AE%9A%E4%B9%89%E5%87%BD%E6%95%B0/1.htm">自定义函数</a> <div>1. 什么是Hive UDF Hive是基于Hadoop中的MapReduce,提供HQL查询的数据仓库。Hive是一个很开放的系统,很多内容都支持用户定制,包括: 文件格式:Text File,Sequence File 内存中的数据格式: Java Integer/String, Hadoop IntWritable/Text 用户提供的 map/reduce 脚本:不管什么</div> </li> <li><a href="/article/1805.htm" title="杀掉nginx进程后丢失nginx.pid,如何重新启动nginx" target="_blank">杀掉nginx进程后丢失nginx.pid,如何重新启动nginx</a> <span class="text-muted">ronin47</span> <a class="tag" taget="_blank" href="/search/nginx+%E9%87%8D%E5%90%AF+pid%E4%B8%A2%E5%A4%B1/1.htm">nginx 重启 pid丢失</a> <div>nginx进程被意外关闭,使用nginx -s reload重启时报如下错误:nginx: [error] open() “/var/run/nginx.pid” failed (2: No such file or directory)这是因为nginx进程被杀死后pid丢失了,下一次再开启nginx -s reload时无法启动解决办法:nginx -s reload 只是用来告诉运行中的ng</div> </li> <li><a href="/article/1932.htm" title="UI设计中我们为什么需要设计动效" target="_blank">UI设计中我们为什么需要设计动效</a> <span class="text-muted">brotherlamp</span> <a class="tag" taget="_blank" href="/search/UI/1.htm">UI</a><a class="tag" taget="_blank" href="/search/ui%E6%95%99%E7%A8%8B/1.htm">ui教程</a><a class="tag" taget="_blank" href="/search/ui%E8%A7%86%E9%A2%91/1.htm">ui视频</a><a class="tag" taget="_blank" href="/search/ui%E8%B5%84%E6%96%99/1.htm">ui资料</a><a class="tag" taget="_blank" href="/search/ui%E8%87%AA%E5%AD%A6/1.htm">ui自学</a> <div>随着国际大品牌苹果和谷歌的引领,最近越来越多的国内公司开始关注动效设计了,越来越多的团队已经意识到动效在产品用户体验中的重要性了,更多的UI设计师们也开始投身动效设计领域。 但是说到底,我们到底为什么需要动效设计?或者说我们到底需要什么样的动效?做动效设计也有段时间了,于是尝试用一些案例,从产品本身出发来说说我所思考的动效设计。 一、加强体验舒适度 嗯,就是让用户更加爽更加爽的用你的产品。 </div> </li> <li><a href="/article/2059.htm" title="Spring中JdbcDaoSupport的DataSource注入问题" target="_blank">Spring中JdbcDaoSupport的DataSource注入问题</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a> <div>参考以下两篇文章: http://www.mkyong.com/spring/spring-jdbctemplate-jdbcdaosupport-examples/ http://stackoverflow.com/questions/4762229/spring-ldap-invoking-setter-methods-in-beans-configuration Sprin</div> </li> <li><a href="/article/2186.htm" title="数据库连接池的工作原理" target="_blank">数据库连接池的工作原理</a> <span class="text-muted">chicony</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0/1.htm">数据库连接池</a> <div>       随着信息技术的高速发展与广泛应用,数据库技术在信息技术领域中的位置越来越重要,尤其是网络应用和电子商务的迅速发展,都需要数据库技术支持动 态Web站点的运行,而传统的开发模式是:首先在主程序(如Servlet、Beans)中建立数据库连接;然后进行SQL操作,对数据库中的对象进行查 询、修改和删除等操作;最后断开数据库连接。使用这种开发模式,对</div> </li> <li><a href="/article/2313.htm" title="java 关键字" target="_blank">java 关键字</a> <span class="text-muted">CrazyMizzz</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div> 关键字是事先定义的,有特别意义的标识符,有时又叫保留字。对于保留字,用户只能按照系统规定的方式使用,不能自行定义。 Java中的关键字按功能主要可以分为以下几类:    (1)访问修饰符       public,private,protected       p</div> </li> <li><a href="/article/2440.htm" title="Hive中的排序语法" target="_blank">Hive中的排序语法</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/%E6%8E%92%E5%BA%8F/1.htm">排序</a><a class="tag" taget="_blank" href="/search/hive/1.htm">hive</a><a class="tag" taget="_blank" href="/search/order+by/1.htm">order by</a><a class="tag" taget="_blank" href="/search/DISTRIBUTE+BY/1.htm">DISTRIBUTE BY</a><a class="tag" taget="_blank" href="/search/sort+by/1.htm">sort by</a> <div>Hive中的排序语法 2014.06.22 ORDER BY hive中的ORDER BY语句和关系数据库中的sql语法相似。他会对查询结果做全局排序,这意味着所有的数据会传送到一个Reduce任务上,这样会导致在大数量的情况下,花费大量时间。 与数据库中 ORDER BY 的区别在于在hive.mapred.mode = strict模式下,必须指定 limit 否则执行会报错。</div> </li> <li><a href="/article/2567.htm" title="单态设计模式" target="_blank">单态设计模式</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a> <div>  单例模式(Singleton)用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。 <?phpclass Example{    // 保存类实例在此属性中    private static&</div> </li> <li><a href="/article/2694.htm" title="svn locked" target="_blank">svn locked</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/Lock/1.htm">Lock</a> <div>post-commit hook failed (exit code 1) with output: svn: E155004: Working copy 'D:\xx\xxx' locked svn: E200031: sqlite: attempt to write a readonly database svn: E200031: sqlite: attempt to write a </div> </li> <li><a href="/article/2821.htm" title=" ARM寄存器学习" target="_blank"> ARM寄存器学习</a> <span class="text-muted">e200702084</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/c/1.htm">c</a><a class="tag" taget="_blank" href="/search/C%23/1.htm">C#</a><a class="tag" taget="_blank" href="/search/F%23/1.htm">F#</a> <div>无论是学习哪一种处理器,首先需要明确的就是这种处理器的寄存器以及工作模式。     ARM有37个寄存器,其中31个通用寄存器,6个状态寄存器。 1、不分组寄存器(R0-R7)     不分组也就是说说,在所有的处理器模式下指的都时同一物理寄存器。在异常中断造成处理器模式切换时,由于不同的处理器模式使用一个名字相同的物理寄存器,就是</div> </li> <li><a href="/article/2948.htm" title="常用编码资料" target="_blank">常用编码资料</a> <span class="text-muted">gengzg</span> <a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A0%81/1.htm">编码</a> <div> List<UserInfo> list=GetUserS.GetUserList(11); String json=JSON.toJSONString(list); HashMap<Object,Object> hs=new HashMap<Object, Object>(); for(int i=0;i<10;i++) { </div> </li> <li><a href="/article/3075.htm" title="进程 vs. 线程" target="_blank">进程 vs. 线程</a> <span class="text-muted">hongtoushizi</span> <a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B/1.htm">线程</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/%E8%BF%9B%E7%A8%8B/1.htm">进程</a> <div>我们介绍了多进程和多线程,这是实现多任务最常用的两种方式。现在,我们来讨论一下这两种方式的优缺点。 首先,要实现多任务,通常我们会设计Master-Worker模式,Master负责分配任务,Worker负责执行任务,因此,多任务环境下,通常是一个Master,多个Worker。 如果用多进程实现Master-Worker,主进程就是Master,其他进程就是Worker。 如果用多线程实现</div> </li> <li><a href="/article/3202.htm" title="Linux定时Job:crontab -e 与 /etc/crontab 的区别" target="_blank">Linux定时Job:crontab -e 与 /etc/crontab 的区别</a> <span class="text-muted">Josh_Persistence</span> <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/crontab/1.htm">crontab</a> <div>一、linux中的crotab中的指定的时间只有5个部分:* * * * * 分别表示:分钟,小时,日,月,星期,具体说来: 第一段 代表分钟 0—59 第二段 代表小时 0—23 第三段 代表日期 1—31 第四段 代表月份 1—12 第五段 代表星期几,0代表星期日 0—6   如: */1 * * * *   每分钟执行一次。 * </div> </li> <li><a href="/article/3329.htm" title="KMP算法详解" target="_blank">KMP算法详解</a> <span class="text-muted">hm4123660</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E5%AD%97%E7%AC%A6%E4%B8%B2/1.htm">字符串</a><a class="tag" taget="_blank" href="/search/KMP/1.htm">KMP</a> <div>     字符串模式匹配我们相信大家都有遇过,然而我们也习惯用简单匹配法(即Brute-Force算法),其基本思路就是一个个逐一对比下去,这也是我们大家熟知的方法,然而这种算法的效率并不高,但利于理解。       假设主串s="ababcabcacbab",模式串为t="</div> </li> <li><a href="/article/3456.htm" title="枚举类型的单例模式" target="_blank">枚举类型的单例模式</a> <span class="text-muted">zhb8015</span> <a class="tag" taget="_blank" href="/search/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/1.htm">单例模式</a> <div>E.编写一个包含单个元素的枚举类型[极推荐]。代码如下: public enum MaYun {himself; //定义一个枚举的元素,就代表MaYun的一个实例private String anotherField;MaYun() {//MaYun诞生要做的事情//这个方法也可以去掉。将构造时候需要做的事情放在instance赋值的时候:/** himself = MaYun() {*</div> </li> <li><a href="/article/3583.htm" title="Kafka+Storm+HDFS" target="_blank">Kafka+Storm+HDFS</a> <span class="text-muted">ssydxa219</span> <a class="tag" taget="_blank" href="/search/storm/1.htm">storm</a> <div>cd /myhome/usr/stormbin/storm nimbus &amp;bin/storm supervisor &amp;bin/storm ui &amp;Kafka+Storm+HDFS整合实践kafka_2.9.2-0.8.1.1.tgzapache-storm-0.9.2-incubating.tar.gzKafka安装配置我们使用3台机器搭建Kafk</div> </li> <li><a href="/article/3710.htm" title="Java获取本地服务器的IP" target="_blank">Java获取本地服务器的IP</a> <span class="text-muted">中华好儿孙</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a><a class="tag" taget="_blank" href="/search/%E8%8E%B7%E5%8F%96%E6%9C%8D%E5%8A%A1%E5%99%A8ip%E5%9C%B0%E5%9D%80/1.htm">获取服务器ip地址</a> <div> System.out.println("getRequestURL:"+request.getRequestURL()); System.out.println("getLocalAddr:"+request.getLocalAddr()); System.out.println("getLocalPort:&quo</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>