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/1892546659607441408.htm" title="video标签 获取视频某一帧用来当作封面" target="_blank">video标签 获取视频某一帧用来当作封面</a> <span class="text-muted">外派叙利亚</span> <a class="tag" taget="_blank" href="/search/%E9%9F%B3%E8%A7%86%E9%A2%91/1.htm">音视频</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>//1000代表视频的第1000帧</div> </li> <li><a href="/article/1892536182668062720.htm" title="前后端分离跨域问题解决方案" target="_blank">前后端分离跨域问题解决方案</a> <span class="text-muted">慕容屠苏</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A7%E5%89%8D%E7%AB%AF%E7%88%AC%E5%9D%91%E4%B9%8B%E8%B7%AF/1.htm">大前端爬坑之路</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E5%90%8E%E7%AB%AF%E5%88%86%E7%A6%BB/1.htm">前后端分离</a><a class="tag" taget="_blank" href="/search/%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/1.htm">跨域问题解决方案</a> <div>前后端分离跨域问题解决方案现在的web开发中经常会用到前后分离技术,前后端分解技术,都会涉及到跨域问题。解决跨域问题的方法:第一种解决方案jsonp(不推荐使用)这种方案其实我是不赞同的,第一,在编码上jsonp会单独因为回调的关系,在传入传出还有定义回调函数上都会有编码的”不整洁”.简单阐述jsonp能够跨域是因为javascript的script标签,通过服务器返回script标签的code,</div> </li> <li><a href="/article/1892531390109511680.htm" title="Shopro商城新零售多商户社交电商分销商城系统支持微信公众号、微信小程序、H5、APP" target="_blank">Shopro商城新零售多商户社交电商分销商城系统支持微信公众号、微信小程序、H5、APP</a> <span class="text-muted">狂团商城小师妹</span> <a class="tag" taget="_blank" href="/search/%E5%8D%9A%E7%BA%B3miui52086/1.htm">博纳miui52086</a><a class="tag" taget="_blank" href="/search/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">微信小程序</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a><a class="tag" taget="_blank" href="/search/%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%B9%B3%E5%8F%B0/1.htm">微信公众平台</a> <div>新零售解决方案重新建立消费者、货物、经营场所三者之间的联系。线上线下联合发力,以消费者体验为核心,全面布局新零售会员管理更便捷规范管理会员信息一目了然,可自动生成会员消费标签,帮助您制定个性化会员营销方案提高会员粘性将会员资源转化为订单。商城管理更省心规范管理会员信息一目了然,可自动生成会员消费标签,帮助您制定个性化会员营销方案提高会员粘性将会员资源转化为订单。社交电商解决方案社交电商已成为线上购</div> </li> <li><a href="/article/1892521549492187136.htm" title="科普:Docker run的相关事项" target="_blank">科普:Docker run的相关事项</a> <span class="text-muted">人工干智能</span> <a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/eureka/1.htm">eureka</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>一、镜像名(含标签)太长如,通过如下命令行:dockerpulldesignthru2019/dify:56c6d1af0944dbdb5e0115cb623ff0e118a4ac62拉取的镜像名(及标签)太长,可以通过改名的方法变短。在Docker中,拉取到本地的镜像可以改名。本质上,这并不是直接修改镜像本身,而是为镜像添加一个新的标签(tag),因为Docker中的镜像名称和标签其实就是对镜像</div> </li> <li><a href="/article/1892519657118691328.htm" title="DeepSeek爆火背后:AI如何助力GIS发展" target="_blank">DeepSeek爆火背后:AI如何助力GIS发展</a> <span class="text-muted">GIS前端嘉欣</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/GIS/1.htm">GIS</a><a class="tag" taget="_blank" href="/search/webgis/1.htm">webgis</a> <div>2025年的春节,一款名为DeepSeek的AI工具以“推理能力超群”“性价比碾压巨头”的标签火遍全网:日活用户突破3000万,微信搜索接入其长思考模式,三大电信运营商全面部署其开源框架。这场由低成本+高性能+开源驱动的技术革命,不仅让AI开发门槛大幅降低,更预示着一个全新的产业趋势——AI与GIS的深度融合,正在重塑城市、环境和商业的底层逻辑。012025年,AI+GIS深度融合的四大趋势1.城</div> </li> <li><a href="/article/1892503270987984896.htm" title="(九万字)面向2025年BOSS直聘人工智能算法工程师高频面试题解析" target="_blank">(九万字)面向2025年BOSS直聘人工智能算法工程师高频面试题解析</a> <span class="text-muted">快撑死的鱼</span> <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/%E5%9B%9E%E5%BD%92/1.htm">回归</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/pytorch/1.htm">pytorch</a> <div>面向2025年BOSS直聘人工智能算法工程师高频面试题解析1.机器学习(ML)理论解析机器学习是让计算机从数据中学习规律的一套方法论,包含监督学习、无监督学习和强化学习等范式。在监督学习中,给定带标签的数据,算法尝试学习从输入到输出的映射关系;无监督学习则在缺乏标签的情况下挖掘数据内在结构;强化学习则让智能体通过与环境交互、依据奖赏反馈来改进策略(Q-learning-Wikipedia)。机器学</div> </li> <li><a href="/article/1892485474463838208.htm" title="深度学习之目标检测的常用标注工具" target="_blank">深度学习之目标检测的常用标注工具</a> <span class="text-muted">铭瑾熙</span> <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%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/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/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/1.htm">目标检测</a><a class="tag" taget="_blank" href="/search/%E7%9B%AE%E6%A0%87%E8%B7%9F%E8%B8%AA/1.htm">目标跟踪</a> <div>1LabelImgLabelImg是一款开源的图像标注工具,标签可用于分类和目标检测,它是用Python编写的,并使用Qt作为其图形界面,简单好用。注释以PASCALVOC格式保存为XML文件,这是ImageNet使用的格式。此外,它还支持COCO数据集格式。2labelmelabelme是一款开源的图像/视频标注工具,标签可用于目标检测、分割和分类。灵感是来自于MIT开源的一款标注工具Label</div> </li> <li><a href="/article/1892473365688545280.htm" title="Mybatis判断问题:深入解析与实战案例" target="_blank">Mybatis判断问题:深入解析与实战案例</a> <span class="text-muted">DTcode7</span> <a class="tag" taget="_blank" href="/search/sql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9B%B8%E5%85%B3/1.htm">sql数据库相关</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/SQL/1.htm">SQL</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%BC%80%E5%8F%91/1.htm">数据库开发</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a> <div>Mybatis判断问题:深入解析与实战案例基础概念与作用说明``标签``,``,````示例一:基本的``标签使用说明示例二:``,``,``的使用说明示例三:使用``标签简化条件语句说明实际工作中的使用技巧自行拓展内容在现代企业级应用开发中,MyBatis作为一款优秀的持久层框架,以其灵活的SQL映射机制和强大的动态SQL功能,深受广大开发者的喜爱。然而,在使用过程中,如何准确地进行条件判断,特</div> </li> <li><a href="/article/1892465546335678464.htm" title="Ubuntu切换终端快捷键" target="_blank">Ubuntu切换终端快捷键</a> <span class="text-muted">yangsong4353</span> <a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/shell/1.htm">shell</a><a class="tag" taget="_blank" href="/search/term/1.htm">term</a> <div>在Ubuntu系统中,使用终端(Terminal)进行操作时,掌握一些快捷键可以大大提高工作效率。以下是一些常用的终端快捷键及其功能:打开和关闭终端打开终端:Ctrl+Alt+T关闭终端:Ctrl+D标签页操作新建标签页:Ctrl+Shift+T关闭标签页:Ctrl+Shift+W切换标签页:Alt+数字键(如Alt+1,Alt+2等)或Ctrl+PageUp/PageDown复制和粘贴复制:Ct</div> </li> <li><a href="/article/1892464158230769664.htm" title="【自然语言处理|迁移学习-08】:中文语料完型填空" target="_blank">【自然语言处理|迁移学习-08】:中文语料完型填空</a> <span class="text-muted">爱学习不掉头发</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/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86%EF%BC%88NLP%EF%BC%89/1.htm">自然语言处理(NLP)</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/1.htm">自然语言处理</a><a class="tag" taget="_blank" href="/search/%E8%BF%81%E7%A7%BB%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>文章目录1中文语料完型填空任务介绍2数据集加载及处理3定义下游任务模型4模型训练5.模型测试1中文语料完型填空任务介绍任务介绍:完成中文语料完型填空完型填空是一个分类问题,[MASK]单词有21128种可能数据构建实现分析:使用迁移学习方式完成使用预训练模型bert模型提取文特征,后面添加全连接层和softmax进行单标签多分类2数据集加载及处理数据介绍:数据文件有三个train.csv,test</div> </li> <li><a href="/article/1892449143461310464.htm" title="Python+Playwright常用元素定位方法" target="_blank">Python+Playwright常用元素定位方法</a> <span class="text-muted">HAMYHF</span> <a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%8A%9F%E8%83%BD%E6%B5%8B%E8%AF%95/1.htm">功能测试</a> <div>CSSselector选择器在CSS中,定位元素主要通过选择器完成,以下是几种常见的CSS选择器定位方法:标签选择器(element):直接使用HTML元素名称来定位,例如p会选择所有段落元素。属性选择器(attribute):选择所有具有指定属性的元素,无论该属性的值是什么。例如,[title]会选择所有包含title属性的元素。选择具有指定属性,并且该属性值完全等于给定值的元素。例如,[typ</div> </li> <li><a href="/article/1892439165430198272.htm" title="容器docker k8s相关的问题汇总及排错" target="_blank">容器docker k8s相关的问题汇总及排错</a> <span class="text-muted">weixin_43806846</span> <a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/kubernetes/1.htm">kubernetes</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a> <div>1.明确问题2.排查方向2.1、docker方面dockerlogs-f容器IDdocker的网络配置问题。2.2、k8s方面node组件问题pod的问题(方式kubectldescribepopod的名称-n命名空间&&kubectllogs-fpod的名称-n命名空间)调度的问题(污点、节点选择器与标签不匹配、存储卷的问题)service问题(访问不了,ingress的问题、service标签</div> </li> <li><a href="/article/1892403467411058688.htm" title="网页中加载 SVG 的七大方式" target="_blank">网页中加载 SVG 的七大方式</a> <span class="text-muted">前端熊猫</span> <a class="tag" taget="_blank" href="/search/Svg/1.htm">Svg</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/svg/1.htm">svg</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a> <div>一、直接使用标签加载外部SVG文件优点:简单易用:与加载其他图片格式(如PNG、JPEG)相同。浏览器支持良好:现代浏览器普遍支持。可缓存:SVG文件可以被浏览器缓存,减少重复请求。缺点:无法直接操作SVG内部元素:如果需要对SVG内部的元素进行交互或样式修改,这种方法不适用。适用场景:静态图像展示:仅需要展示SVG图像,不需要与之交互。二、将SVG作为CSS背景图片.icon{width:100</div> </li> <li><a href="/article/1892400189780586496.htm" title="js如何直接下载文件流" target="_blank">js如何直接下载文件流</a> <span class="text-muted">涔溪</span> <a class="tag" taget="_blank" href="/search/js/1.htm">js</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>在JavaScript中直接处理文件下载,尤其是在处理文件流的情况下,通常涉及到使用fetchAPI或者XMLHttpRequest来获取文件流,并通过创建一个临时的标签(锚点元素)触发下载。以下是使用fetchAPI的一个示例:fetch('你的文件URL',{method:'GET',headers:{//如果需要的话,可以在这里添加请求头}}).then(response=>response</div> </li> <li><a href="/article/1892400063376846848.htm" title="scoped作用原理及样式穿透的应用" target="_blank">scoped作用原理及样式穿透的应用</a> <span class="text-muted">太阳与星辰</span> <a class="tag" taget="_blank" href="/search/Vue2/1.htm">Vue2</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>scoped作用原理及样式穿透的应用(1)scoped作用原理(2)对第三条的详细解释(3)场景----微调第三方库样式(4)样式穿透(5)补充(1)scoped作用原理scoped是Vue样式作用域的一个特性,相信很多人经常在项目中用它来避免样式污染(即样式隔离)。当我们在一个组件中给style标签加上scoped时候,它会遵循以下三个规则,如下为组件实例生成一个唯一标识(可以称为文件指纹),给</div> </li> <li><a href="/article/1892385443702435840.htm" title="sklearn.ConfusionMatrixDisplay可视化混淆矩阵" target="_blank">sklearn.ConfusionMatrixDisplay可视化混淆矩阵</a> <span class="text-muted">Cachel wood</span> <a class="tag" taget="_blank" href="/search/python%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%92%8C%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98/1.htm">python机器学习和数据挖掘</a><a class="tag" taget="_blank" href="/search/sklearn/1.htm">sklearn</a><a class="tag" taget="_blank" href="/search/%E7%9F%A9%E9%98%B5/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/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><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>文章目录ConfusionMatrixDisplay详细解释更多定制化ConfusionMatrixDisplayConfusionMatrixDisplay是scikit-learn库中用于可视化混淆矩阵的一个实用工具。混淆矩阵是一种常用的评估分类模型性能的工具,它可以直观地展示模型在各个类别上的预测结果与真实标签之间的关系。下面详细介绍如何使用ConfusionMatrixDisplay进行混</div> </li> <li><a href="/article/1892380642755276800.htm" title="基于STM32的智能图书馆管理系统" target="_blank">基于STM32的智能图书馆管理系统</a> <span class="text-muted">STM32发烧友</span> <a class="tag" taget="_blank" href="/search/stm32/1.htm">stm32</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a> <div>1.引言传统图书馆管理存在借还效率低、书籍定位困难等问题。本文设计了一款基于STM32的智能图书馆管理系统,通过RFID技术、智能导航与自助服务终端,实现图书精准管理,提升读者服务体验。2.系统设计2.1硬件设计主控芯片:STM32F429ZI,集成LCD控制器与硬件JPEG解码感知模块:RFID读写器(MFRC522):识别图书标签红外传感器(E18-D80NK):检测书籍存取状态重量传感器(H</div> </li> <li><a href="/article/1892322013918326784.htm" title="使用LM Studio在WordPress基于大模型原创文章上稿进行SEO优化" target="_blank">使用LM Studio在WordPress基于大模型原创文章上稿进行SEO优化</a> <span class="text-muted">Mr数据杨</span> <a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E6%8A%80%E6%9C%AF/1.htm">自然语言技术</a><a class="tag" taget="_blank" href="/search/wordpress/1.htm">wordpress</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%A8%A1%E5%9E%8B/1.htm">大模型</a><a class="tag" taget="_blank" href="/search/seo/1.htm">seo</a><a class="tag" taget="_blank" href="/search/1024%E7%A8%8B%E5%BA%8F%E5%91%98%E8%8A%82/1.htm">1024程序员节</a> <div>在进行自动化文章生成与发布的流程中,首先需要确保基础配置的完善性和数据的准确性。通过手动设置分类和标签,文章能够在发布时被准确归类,从而提升SEO的效果。通过Excel表格的方式管理这些分类与标签,结合Python脚本,可以高效地实现自动化文章的生成和发布。该流程依赖于对WordPress数据库的操作,包括标签的批量导入、分类和标签的映射,以及通过AI生成内容的自动发布。全面的配置不仅节省了手动处</div> </li> <li><a href="/article/1892296529092341760.htm" title="前端面试题(HTML篇)" target="_blank">前端面试题(HTML篇)</a> <span class="text-muted">每天一点点~</span> <a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>1.网络中使用最多的图片格式有哪些?JPEG,GIF,PNG最流行的是JPEG格式,可以把文件压缩到最小在PS以JPEG格式存储时,提供11级压缩等级2.Doctype作用?严格模式与混杂模式如何区分?它们有何意义?声明文档类型声明位于位于HTML文档中的第一行,处于标签之前DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。标准模式(严格模式)浏览器按照W3C的标准解析执行代码标准模式(严</div> </li> <li><a href="/article/1892211766507663360.htm" title="AngularJS中文手册前半部分学习" target="_blank">AngularJS中文手册前半部分学习</a> <span class="text-muted">CV战士plus</span> <a class="tag" taget="_blank" href="/search/angular.js/1.htm">angular.js</a><a class="tag" taget="_blank" href="/search/angular.js/1.htm">angular.js</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>AngularJS简介AngularJS的中文参考手册AngularJS的使用AngularJS是一个JS框架,通过指令(ng-directives)扩展了HTML,且通过表达式绑定数据到HTML,用于开发单一页面应用程序(SPAs:SinglePageApplications)可以通过script标签添加到网页中(建议把脚本放在元素的底部。这会提高网页加载速度,因为HTML加载不受制于脚本加载。</div> </li> <li><a href="/article/1892203451027353600.htm" title="vue3中<el-table-column>状态的显示" target="_blank">vue3中<el-table-column>状态的显示</a> <span class="text-muted">BillKu</span> <a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/elementui/1.htm">elementui</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>方法1:使用作用域插槽+标签{{row.status===1?'启用':'禁用'}}consttableData=[{id:1,name:'数据1',status:1},{id:2,name:'数据2',status:0},//...]方法2:使用formatter格式化显示conststatusFormatter=(row)=>{returnrow.status===1?'启用':'禁用'}自定</div> </li> <li><a href="/article/1892201180193419264.htm" title="最少前缀操作问题--感受不到动态规划,怎么办怎么办" target="_blank">最少前缀操作问题--感受不到动态规划,怎么办怎么办</a> <span class="text-muted">幼儿园口算大王</span> <a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/1.htm">动态规划</a> <div>题目:标签:动态规划(应该是双指针的,不理解)小U和小R有两个字符串,分别是S和T,现在小U需要通过对S进行若干次操作,使其变成T的一个前缀。操作可以是修改S的某一个字符,或者删除S末尾的字符。现在你需要帮助小U计算出,最少需要多少次操作才能让S变成T的前缀。测试样例样例1:输入:S="aba",T="abb"输出:1样例2:输入:S="abcd",T="efg"输出:4样例3:输入:S="xyz</div> </li> <li><a href="/article/1892181126793981952.htm" title="React学习笔记04" target="_blank">React学习笔记04</a> <span class="text-muted">充气大锤</span> <a class="tag" taget="_blank" href="/search/React%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/1.htm">React学习笔记</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</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/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>一、理解组件通信组件通信就是组件间的数据传递,根据组件嵌套关系的不同,有不同的通信方法。在Vue中组件通信是我们组件间传递数据的一种最常用的方法,我们在Vue中使用props来实现父传子,用$emit实现子传父,在React中如何实现呢?1.1、父传子:1、父组件传递数据:在子组件标签身上绑定属性2、子组件接收数据:props的参数functionSon(props){return{props.n</div> </li> <li><a href="/article/1892152376232570880.htm" title="mac新环境" target="_blank">mac新环境</a> <span class="text-muted">大油油</span> <a class="tag" taget="_blank" href="/search/macos/1.htm">macos</a><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> <div>1、maven设置阿里云镜像打开Maven的settings.xml文件。找到标签,如果没有,可以手动添加。在标签内部添加以下内容:nexus-aliyun*Nexusaliyunhttp://maven.aliyun.com/nexus/content/groups/public这个配置告诉Maven使用阿里云的镜像作为所有仓库的镜像。如果你更喜欢使用淘宝镜像,也可以将URL修改为淘宝的镜像地址</div> </li> <li><a href="/article/1892139021031763968.htm" title="HTML5的新增标签有哪些?" target="_blank">HTML5的新增标签有哪些?</a> <span class="text-muted">「已注销」</span> <a class="tag" taget="_blank" href="/search/HTML5/1.htm">HTML5</a> <div>2019-07-3009:46我们都知道,想要成为一名合格的前端开发人员,掌握好HTML5是一个重要的先决条件,相比较于HTML,HTML5中新增了许多功能标签,那么这么标签都有哪些呢?格式:定义文本的文本方向,使其脱离其周围文本的方向设置。定义有记号的文本。定义预定义范围内的度量。定义任何类型的任务的进度。定义若浏览器不支持ruby元素显示的内容。定义ruby注释的解释。定义ruby注释。定义日</div> </li> <li><a href="/article/1892138264207355904.htm" title="1 html5-新标签" target="_blank">1 html5-新标签</a> <span class="text-muted">xiaolongyu3</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%96%B0%E5%AD%A6/1.htm">前端新学</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a> <div>年龄稍大一点的码农可能见证了html的发展,亲历了头声明的变化,但是现在起步就是html5,那么html有哪些不为大家常用的新东西呢,这一章我先来谈谈这个问题。1dialog标签——弹窗标签。弹窗可能前端一路走来,见过很多。甚至现在我们在用各种UI库的时候这个弹窗也是必须的一个功能。这个标签支持的api:show:展示弹窗框,采用决定定位,showModal:展示弹窗,并带有遮罩,采用了一个特殊的</div> </li> <li><a href="/article/1892136749694513152.htm" title="HTMl5新增特性有哪些?" target="_blank">HTMl5新增特性有哪些?</a> <span class="text-muted">番茄牛腩汤</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a> <div>(1)新增了语义化标签(2)新增了音频视频标签(3)新增了canvas和svg绘图(4)新增了地理定位(navigator.geolocation)(5)新增了拖拽API(drapable)(6)新增了多线程技术webworker(7)新增了即时通讯websocket</div> </li> <li><a href="/article/1892135487041236992.htm" title="HTML5 新特性有哪些?" target="_blank">HTML5 新特性有哪些?</a> <span class="text-muted">IT木昜</span> <a class="tag" taget="_blank" href="/search/%E5%A4%A7%E7%99%BD%E8%AF%9D%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%A2%98/1.htm">大白话前端面试题</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a> <div>HTML5新特性,你知道几个?语义化标签:HTML5引入了一系列语义化标签,比如代表网页的头部,就像是一本书的封面和目录部分,包含网站标志、导航栏等重要信息;用于导航链接,是网页的“交通指示牌”,方便用户快速找到不同页面;表示独立的文章内容,每一篇新闻报道、博客文章都可以放在这里;用来划分页面的不同区域,像一个商场里不同的楼层分区;代表网页底部,一般放版权信息、联系方式等。这些标签让网页结构更清晰</div> </li> <li><a href="/article/1892132588710064128.htm" title="HTML5+CSS3【容器元素、 HTML5新增布局标签、视频和音频 、HTML5新增标签】(五)-全面详解(学习总结---从入门到深化)" target="_blank">HTML5+CSS3【容器元素、 HTML5新增布局标签、视频和音频 、HTML5新增标签】(五)-全面详解(学习总结---从入门到深化)</a> <span class="text-muted">童小纯</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E7%B3%BB%E5%88%97---%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E6%B7%B1%E5%8C%96/1.htm">前端系列---从入门到深化</a><a class="tag" taget="_blank" href="/search/css3/1.htm">css3</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a> <div>作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步如果感觉博主的文章还不错的话,请三连支持一下博主哦博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人目录容器元素(div)学习效果反馈HTM</div> </li> <li><a href="/article/1892131196566040576.htm" title="html5新增的标签有哪些" target="_blank">html5新增的标签有哪些</a> <span class="text-muted">北原_春希</span> <a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a> <div>HTML5新增的标签主要可以分为几类,以下是按照类别进行分点表示和归纳的HTML5新增标签:结构性标签::定义文档或节的头部。:定义导航链接。:定义文档中的独立节。:定义文档、页面、应用或网站中独立的内容区域。:定义页面的侧边栏内容。:定义文档或节的页脚。:定义文档的主体内容。多媒体标签::定义视频或电影。:定义音频内容。:为和元素定义媒体资源。:为和元素定义文本轨道。:定义嵌入的内容,比如插件。</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>