??xml version="1.0" encoding="utf-8" standalone="yes"?>中文字幕在线一区二区三区,亚洲精品久久久久久久久久久久久,国产永久av在线http://www.aygfsteel.com/conans/category/47040.html你越挣扎我就兴?/description>zh-cnWed, 17 Nov 2010 02:10:50 GMTWed, 17 Nov 2010 02:10:50 GMT60在struts2下用Velocity1.6, velocity tools 1.4的Layout功能http://www.aygfsteel.com/conans/articles/338191.htmlCONANCONANTue, 16 Nov 2010 08:34:00 GMThttp://www.aygfsteel.com/conans/articles/338191.htmlstruts2默认貌似只是支持VelocityLayoutServlet

那么如何使用VelocityLayoutServlet呢?

首先Q要自己写点代码了,写个extends org.apache.struts2.dispatcher.VelocityResult 的类Q取名曰QVelocityLayoutResult

实现如下Q?/p>

package struts2.velocity;

import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;

import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.PageContext;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.VelocityResult;
import org.apache.struts2.views.JspSupportServlet;
import org.apache.struts2.views.velocity.VelocityManager;
import org.apache.velocity.Template;
import org.apache.velocity.context.Context;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;

public class VelocityLayoutResult extends VelocityResult {

private static final long serialVersionUID = 6020934292083047099L;

private static final Logger LOG = LoggerFactory.getLogger(VelocityLayoutResult.class);

public static String KEY_SCREEN_CONTENT = "screen_content";
public static String KEY_LAYOUT = "layout";
public static final String PROPERTY_DEFAULT_LAYOUT = "tools.view.servlet.layout.default.template";
public static final String PROPERTY_LAYOUT_DIR = "tools.view.servlet.layout.directory";
public static final String PROPERTY_INPUT_ENCODING = "input.encoding";
public static final String PROPERTY_OUTPUT_ENCODING = "output.encoding";
public static final String PROPERTY_CONTENT_TYPE = "default.contentType";

protected VelocityManager velocityManager;
protected String defaultLayout;
protected String layoutDir;
protected String inputEncoding;
protected String outputEncoding;
protected String contentType;

@Override
public void setVelocityManager(VelocityManager mgr) {
   
this.velocityManager = mgr;
   
super.setVelocityManager(mgr);
}

@Override
public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
   ValueStack stack 
= ActionContext.getContext().getValueStack();

   HttpServletRequest request 
= ServletActionContext.getRequest();
   HttpServletResponse response 
= ServletActionContext.getResponse();
   JspFactory jspFactory 
= null;
   ServletContext servletContext 
= ServletActionContext.getServletContext();
   Servlet servlet 
= JspSupportServlet.jspSupportServlet;

   velocityManager.init(servletContext);

   
boolean usedJspFactory = false;
   PageContext pageContext 
= (PageContext) ActionContext.getContext().get(ServletActionContext.PAGE_CONTEXT);

   
if (pageContext == null && servlet != null) {
    jspFactory 
= JspFactory.getDefaultFactory();
    pageContext 
= jspFactory.getPageContext(servlet, request, response, nulltrue8192true);
    ActionContext.getContext().put(ServletActionContext.PAGE_CONTEXT, pageContext);
    usedJspFactory 
= true;
   }

   
try {
    String encoding 
= getEncoding(finalLocation);

    String contentType 
= getContentType(finalLocation);

    
if (encoding != null) {
     contentType 
= contentType + ";charset=" + encoding;
    }

    Template t 
= getTemplate(stack, velocityManager.getVelocityEngine(), invocation, finalLocation, encoding);

    Context context 
= createContext(velocityManager, stack, request, response, finalLocation);
    StringWriter stringWriter 
= new StringWriter();
    t.merge(context, stringWriter);
    context.put(KEY_SCREEN_CONTENT, stringWriter.toString());

    Object obj 
= context.get(KEY_LAYOUT);
    String layout 
= (obj == null? null : obj.toString();

    defaultLayout 
= (String) velocityManager.getVelocityEngine().getProperty(PROPERTY_DEFAULT_LAYOUT);
    layoutDir 
= (String) velocityManager.getVelocityEngine().getProperty(PROPERTY_LAYOUT_DIR);
    
if (!layoutDir.endsWith("/")) {
     layoutDir 
+= '/';
    }

    
if (!layoutDir.startsWith("/")) {
     layoutDir 
= "/" + layoutDir;
    }

    defaultLayout 
= layoutDir + defaultLayout;

    
if (layout == null) {
     layout 
= defaultLayout;
    } 
else {
     layout 
= layoutDir + layout;
    }

    Template layoutVm 
= null;
    
try {
     inputEncoding 
= (String) velocityManager.getVelocityEngine().getProperty(PROPERTY_INPUT_ENCODING);
     layoutVm 
= getTemplate(stack, velocityManager.getVelocityEngine(), invocation, layout, inputEncoding);
    } 
catch (Exception e) {
     LOG.error(
"VelocityLayoutResult: Can't load layout \"" + layout + "\"" + e);

     
if (!layout.equals(defaultLayout)) {
      layoutVm 
= getTemplate(stack, velocityManager.getVelocityEngine(), invocation, defaultLayout,
        inputEncoding);
     }
    }

    outputEncoding 
= (String) velocityManager.getVelocityEngine().getProperty(PROPERTY_OUTPUT_ENCODING);
    Writer writer 
= new OutputStreamWriter(response.getOutputStream(), outputEncoding);
    response.setContentType(contentType);

    layoutVm.merge(context, writer);
    writer.flush();
   } 
catch (Exception e) {
    LOG.error(
"Unable to render Velocity Template, '" + finalLocation + "'", e);
    
throw e;
   } 
finally {
    
if (usedJspFactory) {
     jspFactory.releasePageContext(pageContext);
    }
   }

   
return;
}

}

然后在struts.xml中就可以配置了,我的配置如下Q?/font>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd"
>
<struts>

<constant name="struts.velocity.toolboxlocation" value="WEB-INF/toolbox.xml" />

<constant name="struts.velocity.configfile" value="WEB-INF/velocity.properties" />
<include file="struts-default.xml" />
<package name="default" extends="struts-default">
<result-types>
    
<result-type name="velocity" class="struts2.velocity.VelocityLayoutResult"/>
   
</result-types>
   
<action name="hello" class="test.Hello" method="execute">
    
<result name="success" type="velocity">result.vm</result>
   
</action>
</package>
</struts>


接下来就可以开始velocity layout之旅?/font>








CONAN 2010-11-16 16:34 发表评论
]]>
Velocity文档http://www.aygfsteel.com/conans/articles/338094.htmlCONANCONANMon, 15 Nov 2010 06:51:00 GMThttp://www.aygfsteel.com/conans/articles/338094.html Velocity是一个基于java的模板引擎(template engineQ。它允许MZ仅简单的使用模板语言Qtemplate languageQ来引用由java代码定义的对象?br /> ? Velocity应用于web开发时Q界面设计h员可以和javaE序开发h员同步开发一个遵循MVC架构的web站点Q也是_面设计人员可以只关 注页面的昄效果Q而由javaE序开发h员关注业务逻辑~码。Velocityjava代码从web面中分d来,q样为web站点的长期维护提? 了便利,同时也ؓ我们在JSP和PHP之外又提供了一U可选的Ҏ?br /> Velocity的能力远不止web站点开发这个领域,例如Q它可以从模? QtemplateQ生SQL和PostScript、XMLQ它也可以被当作一个独立工h产生源代码和报告Q或者作为其他系l的集成lg使用? Velocity也可以ؓTurbine web开发架构提供模板服务(template serviceQ。Velocity+Turbine提供一个模板服务的方式允许一个web应用以一个真正的MVC模型q行开发?br />
Velocity能ؓ我们作什么?
The Mud Store Example
? 设你是一家专门出售Mud的在U商店的面设计人员Q让我们暂且U它?#8220;在线MUD商店”。你们的业务很旺Q客户下了各U类型和数量的mud订单。他们都 是通过输入用户名和密码后才登陆C的网站,登陆后就允许他们查看订单q购买更多的mud。现在,一U非常流行的mud正在打折销售。另外有一些客戯? 性的购买另外一U也在打折但是不是很行的Bright Red MudQ由于购买的人ƈ不多所以它被安|在面的边~。所有用L信息都是被跟tƈ存放于数据库中的Q所以某天有一个问题可能会冒出来:Z么不使用 velocity来用户更好的浏览他们感兴趣的商品呢Q?br /> Velocity使得web面的客户化工作非常Ҏ。作Z个web site的设计h员,你希望每个用L陆时都拥有自q面?br /> 你会见了一些公司内的Y件工E师Q你发现他们每个人都同意客户应该拥有h个性化的信息。那让我们把软g工程师应该作的事情发在一边,看一看你应该作些什么吧?br /> 你可能在面内嵌套如下的VTL声明Q?br /> <html>
<body>
Hello $customer.Name!
<table>
#foreach( $mud in $nudsOnSpecial )
#if ( $customer.hasPurchased( $mud ) )
<tr><td>$flogger.getPromo( $mud )</td></tr>
#end
#end
</table>

Velocity Template Language(VTL):AN introduction
VTL意味着提供最单、最Ҏq且最整洁的方式合q面动态内宏V?br /> VTL 使用references来在web site内嵌套动态内容,一个变量就是一U类型的reference。变量是某种cd的refreenceQ它可以指向java代码中的定义Q或者从当前 面内定义的VTL statement得到倹{下面是一个VTL statement的例子,它可以被嵌套到HTML代码中:
  #set ( $a = “Velocity” )
? 所有的VTL statement一Pq个statement以#字符开始ƈ且包含一个directiveQset。当一个在U用戯求你的页面时QVelocity Templating Engine查询整个页面以便发现所有#字符Q然后确定哪些是VTL statementQ哪些不需要VTL作Q何事情?br /> Q字W后紧跟一个directiveQsetӞq个set directive使用一个表辑ּQ用括号封闭)――一个方E式分配一个值给变量。变量被列在左边Q而它的D列在双Q最后他们之间用=号分剌Ӏ?br /> 在上面的例子中,变量?aQ而它的值是Velocity。和其他的references一样以$字符开始,而值L以双引号闭。Velocity中仅有String可以被赋值给变量?br /> C以下的规则:
使用$字符开始的references用于得到什么;使用#字符开始的directives用于作些什么?br /> Hello Velocity World!
一旦某个变量被分配了一个|那么你就可以在HTML文g的Q何地方引用它。在下面的例子中Q一个D分配l?foo变量Qƈ在其后被引用?br /> <html>
<body>
#set ( $foo = “Velocity” )
Hello $foo World!
</body>
</html>
上面的实现结果是在页面上打印“Hello Velocity WorldQ?#8221;
Z使包含VTL directives的statement更具有可L,我们鼓励你在新行开始每个VTL statementQ尽你不是必须q么作。Set directive在后面详细描述?br /> 注释
单行注释Q?br />   ## This is a single line comment.
多行注释Q?br />   #*
   Thus begins a multi-line comment. Online visitors won’t
   see this text because the Velocity Templating Engine will
ignore it.
  *#
文档格式Q?br />   #**
   This is a VTL comment block and
   may be used to store such information
as the document author and versioning
   information:
   @version 5
   @author
  *#

References
? VTL中有三种cd的referencesQ变?variables)、属?properties)、方?methods)。作Z个用VTL? 面设计者,你和你的工程师必dreferences的名U达成共识,以便你可以在你的template中用它们?br /> Everything coming to and from a reference被作Z个String对象处理。如果有一个对?foo是一个Integer对象Q那么Velocity调用它的toString()Ҏ这个对象{型ؓStringcd?br />   变量
  格式要求同java?br />   属?
  例子Q?br />     $customer.Address
    $purchase.Total
$customer.Address 有两U含义。它可以表示Q查找hashtable对象customer中以Address为关键字的|也可以表C用customer对象? getAddress()Ҏ。当你的面被请求时QVelocity确定以上两U方式选用那种Q然后返回适当的倹{?br /> Ҏ
一个方法就是被定义在java中的一D代码,q且它有完成某些有用工作的能力,例如一个执行计和判断条g是否成立、满等。方法是一个由$开始ƈ跟随VTL标识W组成的ReferencesQ一般还包括一个VTLҎ体。例如:
  $customer.getAddress()
  $purchase.getTotal()
  $page.setTitle( “My Home Page” )
  $person.setAttributes( [“Strange”, “Weird”, “Excited”] )
前两个例?customer.getAddress()?purchase.getTotal()看v来挺想上面的属?customer.Address ?$purchase.Total。如果你觉得他们之间有某U联pȝ话,那你是正的?br /> VTL属性可以作为VTLҎ的羃写?customer.Address属性和使用$customer.getAddress()Ҏh相同的效果。如果可能的话用属性的方式是比较合理的。属性和Ҏ的不同点在于你能够给一个方法指定一个参数列表?br /> 正式reference标记
reference的正是格式如下:
  ${mudSlinger}        变量
  ${customer.Address}    属?br />   ${purchase.getTotal()}    Ҏ
非正是格式更见常用,但是有时q是使用正是格式比较适合。例如:你希望通过一个变?vice来动态的l织一个字W串?br />   Jack is a $vicemaniac.
本来变量?vice现在却变成了$vicemaniacQ这样Veloctiy׃知道您到底要什么了。所以,应该使用正是格式书写
  Jack is a ${vice}maniac
现在Velocity知道变量?vice而不?vicemaniac?br /> Quiet reference notation
例如Q?br />   <input type=”text” name=”email” value=”$email” />
当页面的form被初始加载时Q变?emailq没有|q时你肯定是希望它能够显CZ个blank text来代替输?#8221;$email”q样的字Dc那么用quiet reference notation比较合适?br />   <input type=”text” name=”email” value=”$!email”/>
q样文本框的初始值就不会是email而是Ig?br /> 正式和quiet格式的reference notation也可一同用,像下面这P
  <input type=”text” name=”email” value=”$!{email}”/>
Getting literal
Velocity使用Ҏ字符$?来帮助它工作Q所以如果要在template里用这些特D字W要格外心。本节将讨论$字符?br />   货币字符
在VTL中?2.5q样的货币标识是没有问题得的QVTL不会它错认为是一个referenceQ因为VTL中的referenceL以一个大写或者小写的字母开始?br /> Escaping valid VTL reference
VTL中?#8220;"”作ؓ逃逸符?br /> 例如Q?br />   #set( $email = “foo” )
  $email
  "$email
  ""$email
  """$email
render为:
  foo
  $email
  "foo
  ""$email
如果email变量没有被定义则
  $email
  "$email
  ""$email
  """$email
被render为:
  $email
  "$email
  ""$email
  """$email
注意QVTL中未被定义的变量被认ؓ是一个字W串Q所以以下例子:
  #set( $foo = “gibbous” )
  $moon = $foo
的输出结果是Q?br /> $moon = gibbous
Case substitution
现在你已l对reference比较熟悉了,你可以将他们高效的应用于你的template了。Velocity利用了很多java规范以方便了设计人员的用。例如:
  $foo
  $foo.getBar()
  ## is the same as
  $foo.Bar

  $data.getUser(“jon”)
  ## is the same as
  $data.User(“jon”)

  $data.getRequest().getServerName()
  # is the same as
  $data.Request.ServerName
  ## is the same as
  ${data.Request.ServerName}
但是Q注意VTL中不会将reference解释为对象的实例变量。例如:$foo.Name被解释为Foo对象的getNameQ)ҎQ而不是Foo对象的Name实例变量?br /> Directives
Reference允许设计者用动态的内容Q而directive使得你可以应用java代码来控制你的显C逻辑Q从而达C所期望的显C效果?br />   #set
  #set directive被用于设|一个reference的倹{例如:
    #set ( $primate = “monkey” )
    #set ( $customer.Behavior = $primate )
赋值左侧的QLHSQ必L一个变量或者属性reference。右侧(RHSQ可以是以下cd中一U:
l  变量reference
l  String literal
l  属性reference
l  Ҏreference
l  number literal
l  ArrayList
下面是应用各U类型的RHS的例子:
  Qset ( $monkey = $bill ) ##变量reference
  Qset ( $monkey.Friend = “monica” ) ##String literal
  Qset ( $monkey.Blame = $whitehouse.Leak )##属性reference
  Qset ( $monkey.Plan = $spindoctor.weave($web) )##Ҏreference
  Qset ( $monkey.Number = 123 )##Number literal
  Qset ( $monkey.Say = [“Not”, $my, “fault”] )##ArrayList
注意Q最后一个例子的取值方法ؓQ?monkey.Say.get(0)
RHS也可以是一个简单的术表达式:
  #set ( $value = $foo + 1 )
  #set ( $value = $bar -1 )
#set ( $value = $foo * $bar )
#set ( $value = $foo / $bar )
如果你的RHS是一个nullQVTL的处理将比较ҎQ它指向一个已l存在的referenceQ这对初学者来讲可能是比较费解的。例如:
  #set ( $resut = $query.criteria(“name”) )
  The result of the first query is $result

  #set ( $resut = $query.criteria(“address”) )
  The result of the second query is $result
如果$query.criteria(“name”)q回一?#8220;bill”Q?query.criteria(“address”)q回的是nullQ则昄的结果如下:
  The result of the first query is bill
  The result of the first query is bill
看看下面的例子:
  #set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = $query.criteria($criterion) )
  #if( $result )
  Query was successful
     #end
#end
? 上面的例子中Q程序将不能的根?result的值决定查询是否成功。在$result?set后(added to the contextQ,它不能被讄回nullQremoved from the contextQ。打印的l果显CZơ查询结果都成功了,但是实际上有一个查询是p|的?br /> Z解决以上问题我们可以通过预先定义的方式:
  #set( $criteria = [“name”, “address”] )
  #foreach( $criterion in $criteria )
    #set( $result = false )
    #set( $result = $query.criteria( $criterion ) )
    #if( $result )
      Query was successful
    #end
  #end
  String Literals
  当你使用#set directiveQString literal闭在一对双引号内?br />     #set ( $directoryRoot = “www” )
    #set ( $templateName = “index.vm” )
    #set ( $template = “$directoryRoot/$tempateName” )
    $template
  上面q段代码的输出结果ؓQwww/index.vm
  但是Q当string literal被封装在单引号内Ӟ它将不被解析Q?br />     #set ( $foo = “bar” )
    $foo
    #set ( $blargh = ‘$foo’ )
  l果Q?br />     bar
    $foo
  上面q个Ҏ可以通过修改velocity.properties文g的stringliterals.interpolate = false的值来改变上面的特性是否有效?br /> 条g语句
  if/elseif/else
当一个web面被生成时使用Velocity?if directriveQ如果条件成立的话可以在面内嵌入文字。例如:
  #if ( $foo )
    <strong>Velocity!</strong>
  #end
上例中的条g语句在以下两种条g下成立:
l  $foo是一个boolean型的变量Q且它的gؓtrue
l  $foo变量的g为null
q里需要注意一点:Velocity context仅仅能够包含对象Q所以当我们?#8220;boolean”时实际上代表的时一个Boolean对象。即便某个方法返回的是一个boolean|Velocity也会利用内省机制它转换Z个Boolean的相同倹{?br /> 如果条g成立Q那?if?end之间的内容将被显C?br /> #elseif?else元素可以?if一同用。例如:
  #if( $foo < 10 )
    <strong> Go North </strong>
  #elseif( $foo == 10 )
    <strong> Go East </strong>
  #elseif( $foo == 6 )
    <strong> Go South </strong>
  #else
    <strong> Go West </strong>
  #end
注意q里的Velocity的数字是作ؓInteger来比较的――其他类型的对象得条件ؓfalseQ但是与java不同它?#8220;Q=”来比较两个|而且velocity要求{号两边的值类型相同?br /> 关系、逻辑q算W?
Velocity中用等h作符判断两个变量的关pR例如:
#set ( $foo = “deoxyribonucleic acid” )
#set ( $bar = “ribonucleic acid” )
#if ( $foo == $foo )
  In this case it’s clear they aren’t equivalent.So…
#else
  They are not equivalent and this will be the output.
#end

Velocity有AND、OR和NOT逻辑q算W。下面是一些例子:
  ## logical AND
  #if( $foo && $bar )
    <strong> This AND that </strong>
  #end

  ## logical OR
  #if ( $foo || $bar )
    <strong>This OR That </strong>
  #end

  ##logical NOT
  #if ( !$foo )
    <strong> NOT that </strong>
  #end
循环
  Foreach循环
  例子Q?br />     <ul>
      #foreach ( $product in $allProducts )
        <li> $product </li>
      #end
    </ul>
  每次循环$allProducts中的一个值都会赋l?product变量?br /> $allProducts 可以是一个Vector、Hashtable或者Array。分配给$product的值是一个java对象Qƈ且可以通过变量被引用。例如:? ?product是一个java的Productc,q且q个产品的名字可以通过调用他的getNameQ)Ҏ得到?br /> 现在我们假设$allProducts是一个HashtableQ如果你希望得到它的key应该像下面这P
<ul>
#foreach ( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key) </li>
#end
</ul>

Velocityq特别提供了得到循环ơ数的方法,以便你可以像下面q样作:
<table>
#foreach ( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
</table>
$velocityCount 变量的名字是Velocity默认的名字,你也可以通过修改velocity.properties文g来改变它。默认情况下Q计C“1”开始,但是? 可以在velocity.properties讄它是?#8220;1”q是?#8220;0”开始。下面就是文件中的配|:
  # Default name of loop counter
  # variable reference
  directive.foreach.counter.name = velocityCount

  # Default starting value of the loop
  # counter variable reference
  directive.foreach.counter.initial.value = 1

include
#include script element允许模板设计者引入本地文件。被引入文g的内容将不会通过模板引擎被render。ؓ了安全的原因Q被引入的本地文件只能在TEMPLATE_ROOT目录下?br />   #inclued ( “one.txt” )
如果您需要引入多个文Ӟ可以用逗号分隔pQ?br />   #include ( “one.gif”, “two.txt”, “three.htm” )
在括号内可以是文件名Q但是更多的时候是使用变量的:
  #inclue ( “greetings.txt”, $seasonalstock )

parse
#parse script element允许模板设计者一个包含VTL的本地文件。Velocity解析其中的VTLqrender模板?br />   #parse( “me.vm” )
像#includeQ?parse接受一个变量而不是一个模ѝQ何由#parse指向的模杉K必须包含在TEMPLATE_ROOT目录下。与#include不同的是Q?parse只能指定单个对象?br /> 你可以通过修改velocity.properties文g的parse_direcive.maxdepth的值来控制一个template可以包含的最?parse的个数――默认值是10?parse是可以递归调用的,例如Q如果dofoo.vm包含如下行:
  Count down.
  #set ( $count = 8 )
  #parse ( “parsefoo.vm” )
  All done with dofoo.vm!
那么在parsefoo.vm模板中,你可以包含如下VTLQ?br />   $count
  #set ( $count = $count – 1 )
  #if ( $count > 0 )
    #parse( “parsefoo.vm” )
  #else
    All done with parsefoo.vm!
  #end
的显C结果ؓQ?br />   Count down.
  8
  7
  6
  5
  4
  3
  2
  1
  0
  All done with parsefoo.vm!
All done with dofoo.vm!

Stop
#stop script element允许模板设计者停止执行模板引擎ƈq回。把它应用于debug是很有帮助的?br />   #stop

Velocimacros
#macro script element允许模板设计者定义一D可重用的VTL template。例如:
  #macro ( d )
  <tr><td></td></tr>
  #end
在上面的例子中Velocimacro被定义ؓdQ然后你可以在MVTL directive中以如下方式调用它:
  #d()
当你的template被调用时QVelocity用<tr><td></td></tr>替换?d()?br /> 每个Velocimacro可以拥有L数量的参数――甚?个参敎ͼ虽然定义时可以随意设|参数数量,但是调用q个Velocimacro时必L定正的参数。下面是一个拥有两个参数的VelocimacroQ一个参数是color另一个参数是arrayQ?br />   #macro ( tablerows $color $somelist )
  #foreach ( $something in $somelist )
    <tr><td bgcolor=$color>$something</td</tr>
  #end
  #end
调用#tablerows VelocimacroQ?br />   #set ( $greatlakes = [ “Superior”, “Michigan”, “Huron”, “Erie”, “Ontario” ] )
  #set ( $color = “blue” )
  <table>
    #tablerows( $color $greatlakes )
  </table>
l过以上的调用将产生如下的显C结果:
  <table>
    <tr><td bgcolor=” blue”> Superior </td></tr>
    <tr><td bgcolor=” blue”> Michigan </td></tr>
    <tr><td bgcolor=” blue”> Huron </td></tr>
    <tr><td bgcolor=” blue”> Erie </td></tr>
    <tr><td bgcolor=” blue”> Ontario </td></tr>
  </table>
Velocimacros 可以在Velocity模板内实现行内定义(inlineQ,也就意味着同一个web site内的其他Velocity模板不可以获得Velocimacros的定义。定义一个可以被所有模板共享的Velocimacro昄是有很多好处 的:它减了在一大堆模板中重复定义的数量、节省了工作旉、减了出错的几率、保证了单点修改?br /> 上面定义?tablerows( $color $list )Velocimacro被定义在一个Velocimacros模板?在velocity.properties中定?里,所以这个macro可以? M规范的模板中被调用。它可以被多ơ应用ƈ且可以应用于不同的目的。例如下面的调用Q?br />   #set ( $parts = [ “volva”, “stipe”, “annulus”, “gills”, “pileus” ] )
  #set ( $cellbgcol = “#CC00FF” )
  <table>
    #tablerows( $cellbgcol $parts )
  </table>
上面VTL生如下的输出Q?br />   <table>
    <tr><td bgcolor=”#CC00FF”> volva </td</tr>
    <tr><td bgcolor=”#CC00FF”> stipe </td</tr>
    <tr><td bgcolor=”#CC00FF”> annulus </td</tr>
    <tr><td bgcolor=”#CC00FF”> gills </td</tr>
    <tr><td bgcolor=”#CC00FF”> pileus </td</tr>
  </table>
  Velocimacro arguments
  Velocimacro可以使用以下M元素作ؓ参数Q?br /> l  ReferenceQQ何以$开头的reference
l  String literalQ?br /> l  Number literalQ?br /> l  IntegerRangeQ[1….3]或者[$foo….$bar]
l  对象数组Q[“a”,”b”,”c”]
l  boolean|true、false
? 一个reference作ؓ参数传递给VelocimacroӞh意reference作ؓ参数时是以名字的形式传递的。这意味着参数的值在每次 Velocimacro内执行时才会被生。这个特性得你可以一个方法调用作为参C递给VelocimacroQ而每ơVelocimacro执行 旉是通过q个Ҏ调用产生不同的值来执行的。例如:
  #macro ( callme $a )
    $a $a $a
  #end
  #callme( $foo.bar() )
执行的结果是Qreference $foo的barQ)Ҏ被执行了三次?br /> 如果你不需要这LҎ可以通过以下ҎQ?br />   #set ( $myval = $foo.bar() )
  #callme ( $myval )

Velocimacro properties
Velocity.properties文g中的某几行能够Velocimacros的实现更加灵zR注意更多的内容可以看Developer Guide?br /> Velocity.properties文g中的velocimacro.libraaryQ一个以逗号分隔的模板库列表。默认情况下Qvelocity查找唯一的一个库QVM_global_library.vm。你可以通过配置q个属性来指定自己的模板库?br /> Velocity.properties 文g中的velocimacro.permissions.allow.inline属性:有两个可选的值true或者falseQ通过它可以确? Velocimacros是否可以被定义在regular template内。默认值是ture――允许设计者在他们自己的模板中定义Velocimacros?br /> Velocity.properties文g中的
velocimacro.permissions.allow.inline.replace.global 属性有两个可选值true和falseQ这个属性允怋用者确定inline的Velocimacro定义是否可以替代全局Velocimacro定义 Q比如在velocimacro.library属性中指定的文件内定义的VelocimacroQ。默认情况下Q此gؓfalse。这样就L本地 Velocimacro定义覆盖全局定义?br /> Velocity.properties文g中的
velocimacro.permissions.allow.inline.local.scale 属性也是有true和false两个可选|默认是false。它的作用是用于定你inline定义的Velocimacros是否仅仅在被定义? template内可见。换句话_如果q个属性设|ؓtrueQ一个inline定义的Velocimacros只能在定义它的template内 用。你可以使用此设|实C个奇妙的VM敲门Qa template can define a private implementation of the second VM that will be called by the first VM when invoked by that template. All other templates are unaffected?br /> Velocity.properties文g中的 velocimacro.context.localscope属性有true和false两个可选|默认gؓfalse。当讄为trueӞM? Velocimacro内通过#set()对context的修改被认ؓ是针Ҏvelocimacro的本地设|,而不会永久的影响内容?br /> Velocity.properties 文g中的velocimacro.library.autoreload属性控制Velocimacro库的自动加蝲。默认是false。当讄? tureӞ对于一个Velocimacro的调用将自动查原始库是否发生了变化,如果变化重新加载它。这个属性得你可以不用重新启动 servlet容器而达到重新加载的效果Q就像你使用regular模板一栗这个属性可以用的前提是resource loader~存是off状态(file.resource.loader.cache = falseQ。注意这个属性实际上是针对开发而非产品的?br /> Velocimacro Trivia
Velocimacro必须被定义在他们被用之前。也是_你的#macro()声明应该出现在用Velocimacros之前?br /> ? 别要注意的是Q如果你试图#parse()一个包?macro()的模ѝ因?parse()发生在运行期Q但是解析器在parsetiem军_一? 看似VM元素的元素是否是一个VM元素Q这?parse()-ing一lVM声明不按照预期的样子工作。ؓ了得到预期的l果Q只需要你单的使用 velocimacro.library使得Velocity在启动时加蝲你的VMs?br /> Escaping VTL directives
VTL directives can be escaped with “"”P使用方式跟VTL的reference使用逃逸符的格式差不多?br />   ## #include( “a.txt” ) renders as <ontents of a.txt>(注释?
  #include( “a.txt” )

  ## "#include( “a.txt” ) renders as "#include( “a.txt” )
  "#include( “a.txt” )

  ## ""#include ( “a.txt” ) renders as "<contents of a.txt>
  ""#include( “a.txt” )
在对在一个directive内包含多个script元素的VTL directives使用逃逸符时要特别心Q比如在一个if-else-end statement内)。下面是VTL的if-statement的典型应用:
  #if ( $jazz )
    Vyacheslav Ganelin
  #end
如果$jazz是tureQ输出将是:
  Vyacheslav Ganelin
如果$jazz是falseQ将没有输出。用逃逸符改变输出。考虑一下下面的情况Q?br />   "#if ( $jazz )
    Vyacheslav Ganelin
  "#end
现在无论$jazz是trueq是falseQ输出结果都是:
  #if ( $jazz )
    Vyacheslav Ganelin
  #end
事实上,׃你用了逃逸符Q?jazzҎ没有被解析为boolean型倹{在逃逸符前用逃逸符是合法的Q例如:
  ""#if ( $jazz )
    Vyacheslav Ganelin
  ""#end
以上E序的显C结果ؓQ?br />   " Vyacheslav Ganelin
  "
但是如果$jazz为falseQ那么将没有输出。(书上说会没有输出Q但是我觉得应该q有?#8220;"”字符被输出。)
VTLQFormatting issues
管在此用户手册中VTL通常都开始一个新行,如下所C:
  #set ( $imperial = [ “Munetaka”, “Koreyasu”, “Hisakira”, “Morikune” ] )
  #foreach ( $shogun in $imperial )
    $shogun
  #end
但是像下面这U写法也是可以的Q?br />   Send me #set($foo = [“$10 and”,”a cake”])#foreach($a in $foo)$a #end please.
上面的代码可以被改写为:
  Send me
  #set ( $foo = [“$10 and “,”a cake”] )
  #foreach ( $a in $foo )
    $a
  #end
  please.
或?br />   Send me
  #set($foo = [“$10 and “,”a cake”])
        #foreach Q?a in $foo Q?a
      #end please.
q两U的输出l构一栗?br /> 其他Ҏ和杂项
  math   在模板中可以使用Velocity内徏的算术函敎ͼ如:加、减、乘、除
    #set ( $foo = $bar + 3 )
    #set ( $foo = $bar - 4 )
    #set ( $foo = $bar * 6 )
    #set ( $foo = $bar / 2 )
  当执行除法时返回一个Integercd的结果。而余C可以使用%来得刎ͼ
    #set ( $foo = $bar % 5 )
在Velocity内用数学计公式时Q只能用像-n,-2,-1,0,1,2,nq样的整敎ͼ而不能用其它类型数据。当一个非整型的对象被使用时它被loggedq且以null作ؓ输出l果?br /> Range Operator
Range operator可以被用于与#set?foreach statement联合使用。对于处理一个整型数l它是很有用的,Range operatorh以下构造Ş式:
  [n..m]
m和n都必L整型Q而m是否大于n则无关紧要。例子:
  First example:
  #foreach ( $foo in [1..5] )
    $foo
  #end

  Second example:
  #foreach ( $bar in [2..-2] )
    $bar
  #end

  Third example:
  #set ( $arr = [0..1] )
  #foreach ( $i in $arr )
    $i
  #end

  Fourth example:
  [1..3]
上面四个例子的输出结果ؓQ?br />   First exampleQ?br />   1 2 3 4 5

  Second exampleQ?br />   2 1 0 -1 -2

  Third exampleQ?br />   0 1

  Fourth exampleQ?br />   [1..3]
注意Qrange operator只在#set?foreach中有效?br /> Advanced IssueQEscaping andQ?br /> 当一个reference?#8220;Q?#8221;分隔Ӟq且在它之前有逃逸符Ӟreference以Ҏ的方式处理。注意这U方式与标准的逃逸方式时不同的。对照如下:
#set ( $foo = “bar” )
Ҏ形式  标准格式
Render?nbsp; Render?nbsp; Render?nbsp; Render?br /> $"!foo  $!foo  "$foo  "$foo
$"!{foo}  $!{foo}  "$!foo  "$!foo
$""!foo  $"!foo  "$!{foo}  "$!{foo}
$"""!foo  $""!foo  ""$!{foo}  "bar
Velocimacro杂记
  Can I user a directive or another VM as an argument to a VM?
  例如Q?center ( #bold( “hello” ) )
  不可以。一个directive的参C用另外一个directive是不合法的?br />   但是Q还是有些事情你可以作的。最单的方式是使用双引P
    #set ( $stuff = “#bold( ‘hello’ )” )
    #center ( $stuff )
  上面的格式也可以~写Z行:
    #center ( “#bold( ‘hello’ ) )
h意在下面的例子中参数被evaluated在Velocimacro内部Q而不是在calling level。例子:
  #macro ( inner $foo )
    inner : $foo
  #end

  #macro ( outer $foo )
    #set ( $bar = “outerlala” )
    outer : $foo
  #end
  
  #set ( $bar = ‘calltimelala’ )
  #outer( “#inner($bar)” )
输出l果为:
  outer : inner : outerlala
CVeloctiy的特性:参数的传递是By Name的。例如:
  #macro ( foo $color )
    <tr bgcolor = $color ><td>Hi</td></tr>
    <tr bgcolor = $color ><td>There</td></tr>
  #end

  #foo ( $bar.rowColor() )
以上代码导致rowColor()Ҏ两次调用Q而不是一ơ。ؓ了避免这U现象的出现Q我们可以按照下面的方式执行Q?br />   #set ( $color = $bar.rowColor() )
  #foo ( $color )
can I register velocimacros via #parse()?
目前QVelocimacros必须在第一ơ被模板调用前被定义。这意味着你的#macro()声明应该出现在用Velocimacros之前?br /> ? 果你试图#parse()一个包?macro() directive的模板,q一Ҏ需要牢记的。因?parse()发生在运行期Q但是解析器在parsetiem军_一个看似VM元素的元素是否是一 个VM元素Q这?parse()-ing一lVM声明不按照预期的样子工作。ؓ了得到预期的l果Q只需要你单的使用 velocimacro.library使得Velocity在启动时加蝲你的VMs?br /> What is velocimacro autoreloadingQ?
velocimacro.library.autoreload是专门ؓ开发而非产品使用的一个属性。此属性的默认值是false?br /> String concatenation
开发h员最帔R的问题是我如何作字符拼接Q在java中是使用“Q?#8221;h完成的?br /> 在VTL里要惛_现同L功能你只需要将需要联合的reference攑ֈ一起就行了。例如:
#set ( $size = “Big” )
#set ( $name = “Ben” )
The clock is $size$name.
输出l果是QThe clock is BigBen.。更有趣的情冉|Q?br />   #set ( $size = “Big” )
  #set ( $name = “Ben” )
  #set ( $clokc = “$size$name” )
  The clock is $clock.
上例也会得到同样的结果。最后一个例子,当你希望混合固定字段C的referenceӞ你需要用标准格式:
  #set ( $size = “Big” )
  #set ( $name = “Ben” )
  #set ( $clock = “${size}Tall$name” )
  The clock is $clock.
输出l果是:The clock is BigTallBen.。用这U格式主要是Z使得$size不被解释?sizeTall?

CONAN 2010-11-15 14:51 发表评论
]]>
վ֩ģ壺 | | | Դ| ¹| ϰ| | | | ʡ| ½| | Ȫ| | ʡ| Ԫı| | ɽ| | | ɰ| | ľ| ӯ| ڶ| | | | ƽ| | ʩ| Ƽ| | Դ| ʡ| | ˮ| | | | ¤|