??xml version="1.0" encoding="utf-8" standalone="yes"?>国产亚洲一区二区三区在线,在线观看午夜亚洲一区,国产精品亚洲A∨天堂不卡http://www.tkk7.com/TrampEagle/category/9793.html学习和生z? zh-cnWed, 28 Feb 2007 08:52:34 GMTWed, 28 Feb 2007 08:52:34 GMT60Velocity?/title><link>http://www.tkk7.com/TrampEagle/articles/49340.html</link><dc:creator>TrampEagle</dc:creator><author>TrampEagle</author><pubDate>Wed, 31 May 2006 14:03:00 GMT</pubDate><guid>http://www.tkk7.com/TrampEagle/articles/49340.html</guid><wfw:comment>http://www.tkk7.com/TrampEagle/comments/49340.html</wfw:comment><comments>http://www.tkk7.com/TrampEagle/articles/49340.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/TrampEagle/comments/commentRss/49340.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/TrampEagle/services/trackbacks/49340.html</trackback:ping><description><![CDATA[Velocity?br />原文引自Q?a >http://www.3doing.net/forums/dispbbs.asp?boardID=57&ID=593&page=1</a><br /><br />Velocity是一个开放源吗的模版引擎Q由apache.org组负责开发,现在最新的版本是Velocity1.3.1<br /><a href="http://<a%20target=_blank%20href=http://jakarta.apache.org/velocity/index.html>http://jakarta.apache.org/velocity/index.html</a>" target="_blank"><font color="#000000">http://jakarta.apache.org/velocity/index.html </font></a>可以了解Velocity的最C息?br />    Velocity允许我们在模版中讑֮变量Q然后在q行Ӟ动态的数据插入到模版中,替换q些变量?br />    例如Q?br /><br /><div id="9lnl3dv" class="codeStyle"><ol><li></li><li>    <<font color="#ff0000">HTML</font>> <br /></li><li>        <BODY> <br /></li><li>            HELLO $CUSTOMERNAME <br /></li><li>        </BODY> <br /></li><li>    </<font color="#ff0000">HTML</font>> </li></ol></div><br />    我们可以在运行时得到客户的名字,然后把它插入到这个模版中替换变量$CUSTOMERNAMEQ整个替换过E是由Velocityq行控制的,而且java的调用代码也非常?br />    如我们可以在java代码中这栯?br /><br /><div id="l3r9dhx" class="codeStyle"><ol><li></li><li>    <i><font color="#339900">//q个文g中设定了Velocity使用的log4j的配|和Velocity的模版文件所在的目录</font></i><br /></li><li>    Velocity.init(<font color="#ff33ff">"D:\\Template\\resource\\jt.properties"</font>); <br /></li><li>    <i><font color="#339900">//模版文g名,模版文g所在的路径在上一条语句中已经讄?/font></i><br /></li><li>    Template template =Velocity.getTemplate(<font color="#ff33ff">"hello.vm"</font>, <font color="#ff33ff">"gb2312"</font>);  <br /></li><li>    <i><font color="#339900">//实例化一个Context</font></i><br /></li><li>    VelocityContext context = <b><font color="#0000ff">new</font></b> VelocityContext();     <br /></li><li>    <i><font color="#339900">//把模版变量的D|到context?/font></i><br /></li><li>    context.put(<font color="#ff33ff">"CUSTOMERNAME"</font>, <font color="#ff33ff">"My First Template Engine ---- Velocity."</font>);         <br /></li><li>    <i><font color="#339900">//开始模版的替换</font></i><br /></li><li>    template.merge(context, writer); <br /></li><li></li><li>    <i><font color="#339900">//写到文g?/font></i><br /></li><li>    <font color="#ff0000">PrintWriter</font> filewriter = <b><font color="#0000ff">new</font></b><font color="#ff0000">PrintWriter</font>(<b><font color="#0000ff">new</font></b><font color="#ff0000">FileOutputStream</font>(outpath),<b><font color="#0000ff">true</font></b>); <br /></li><li>    filewriter.println(writer.toString()); <br /></li><li>    filewriter.close(); </li></ol></div><br />    q就是整个java的代码,非常的简单。如果我们有多个模版变量Q我们仅需要把q些模版变量的D|到context中?br />    <br />    下面我们单的分析一下,Velocity引擎d模板文gӞ它直接输出文件中所有的文本Q但?字符开头的除外Q?W号标识着一个模版变量位|,context.put("CUSTOMERNAME", "My First Template Engine ---- Velocity.");当Velocity模板引擎解析q输出模板的l果Ӟ模板中所有出?CUSTOMERNAME的地斚w插入客L名字Q即被加入到VelocityContext的对象的toString()Ҏq回值将替代Velocity变量Q模板中?开头的变量Q?br />    模板引擎中最强大、用最频繁的功能之一是它通过<b>内徏的映?/b>QReflectionQ引擎查扑֯象信息的能力。这个映像引擎允许用一U方便的Java?”类似的操作W,提取L加入到VelocityContext的对象的M公用Ҏ的|或对象的L数据成员。映像引擎还带来了另外一个改q:快速引用JavaBean的属性。用JavaBean属性的时候,我们可以忽略getҎ和括受请看下面这个模板的例子?br /><br /><div id="3pdrjtt" class="codeStyle"><ol><li></li><li>    <<font color="#ff0000">HTML</font>> <br /></li><li>        <BODY> <br /></li><li>            <font color="#ff0000">Name</font>:         $Customer.<font color="#ff0000">Name</font>() <br /></li><li>            Address:    $Customer.Address() <br /></li><li>            Age:        $Customer.Age() <br /></li><li>        </BODY> <br /></li><li>    </<font color="#ff0000">HTML</font>> </li></ol></div><br />    java的代码:    <br /><br /><div id="zj99999" class="codeStyle"><ol><li></li><li>    <i><font color="#339900">//讄客户信息</font></i><br /></li><li>    Customer mycustomer = <b><font color="#0000ff">new</font></b> Customer(); <br /></li><li>    mycustomer.setName(<font color="#ff33ff">"Velocity"</font>); <br /></li><li>    mycustomer.setAddress(<font color="#ff33ff">"jakarta.apache.org/velocity/index.html"</font>); <br /></li><li>    mycustomer.setAge(2); <br /></li><li>     <br /></li><li>    <i><font color="#339900">//q个文g中设定了Velocity使用的log4j的配|和Velocity的模版文件所在的目录</font></i><br /></li><li>    Velocity.init(<font color="#ff33ff">"D:\\Template\\resource\\jt.properties"</font>); <br /></li><li>    <i><font color="#339900">//模版文g名,模版文g所在的路径在上一条语句中已经讄?/font></i><br /></li><li>    Template template =Velocity.getTemplate(<font color="#ff33ff">"hello.vm"</font>, <font color="#ff33ff">"gb2312"</font>);  <br /></li><li>    <i><font color="#339900">//实例化一个Context</font></i><br /></li><li>    VelocityContext context = <b><font color="#0000ff">new</font></b> VelocityContext();     <br /></li><li>    <i><font color="#339900">//把模版变量的D|到context?/font></i><br /></li><li>    context.put(<font color="#ff33ff">"Customer"</font>, mycustomer);     <br /></li><li>    <i><font color="#339900">//开始模版的替换</font></i><br /></li><li>    template.merge(context, writer); <br /></li><li></li><li>    <i><font color="#339900">//写到文g?/font></i><br /></li><li>    <font color="#ff0000">PrintWriter</font> filewriter = <b><font color="#0000ff">new</font></b><font color="#ff0000">PrintWriter</font>(<b><font color="#0000ff">new</font></b><font color="#ff0000">FileOutputStream</font>(outpath),<b><font color="#0000ff">true</font></b>); <br /></li><li>    filewriter.println(writer.toString()); <br /></li><li>    filewriter.close(); </li></ol></div><br />    输出l果Q?br /><br /><div id="vr9vvd9" class="codeStyle"><ol><li></li><li>    <<font color="#ff0000">HTML</font>> <br /></li><li>        <BODY> <br /></li><li>            <font color="#ff0000">Name</font>:        Velocity <br /></li><li>            Address:    jakarta.apache.orgvelocityindex.html <br /></li><li>            Age:        2 <br /></li><li>        </BODY> <br /></li><li>    </<font color="#ff0000">HTML</font>> </li></ol></div><br />    除了替换变量之外Q象Velocity高引擎q能做其他许多事情,它们有用来比较和q代的内建指令,通过q些指o我们可以完成E序语言中的条g判断语句和@环语句等<br />    <br />    例如Q我们想要输出年龄等?的所有客L信息Q我们可以这样定义我们的模版<br />    模版Q?br /><br /><div id="vdlj3tt" class="codeStyle"><ol><li></li><li>    <<font color="#ff0000">HTML</font>> <br /></li><li>        <BODY> <br /></li><li>            <table> <br /></li><li>                <tr> <br /></li><li>                    <td>名称</td><td>地址</td><td>q龄</td> <br /></li><li>                </tr> <br /></li><li>                #foreach ($Customer in $allCustomer) <br /></li><li>                    #<b><font color="#0000ff">if</font></b>($Customer.Age()==<font color="#ff33ff">"2"</font>) <br /></li><li>                    <tr> <br /></li><li>                        <td>$Customer.<font color="#ff0000">Name</font>()</td> <br /></li><li>                        <td>$Customer.Address()</td> <br /></li><li>                        <td>$Customer.Age()</td> <br /></li><li>                    </tr> <br /></li><li>                    #end <br /></li><li>                #end <br /></li><li>            </table> <br /></li><li>        </BODY> <br /></li><li>    </<font color="#ff0000">HTML</font>> </li></ol></div>    <br /><br />    java的代码:    <br /><br /><div id="bftfnnn" class="codeStyle"><ol><li></li><li>    <i><font color="#339900">//讄客户信息</font></i><br /></li><li>    <font color="#ff0000">ArrayList</font> allMyCustomer = <b><font color="#0000ff">new</font></b><font color="#ff0000">ArrayList</font>(); <br /></li><li>     <br /></li><li>    <i><font color="#339900">//客户1</font></i><br /></li><li>    Customer mycustomer1 = <b><font color="#0000ff">new</font></b> Customer(); <br /></li><li>    mycustomer1.setName(<font color="#ff33ff">"Velocity"</font>); <br /></li><li>    mycustomer1.setAddress(<font color="#ff33ff">"jakarta.apache.org/velocity/index.html"</font>); <br /></li><li>    mycustomer1.setAge(2); <br /></li><li>     <br /></li><li>    <i><font color="#339900">//客户2</font></i><br /></li><li>    Customer mycustomer2 = <b><font color="#0000ff">new</font></b> Customer(); <br /></li><li>    mycustomer2.setName(<font color="#ff33ff">"Tomcat"</font>); <br /></li><li>    mycustomer2.setAddress(<font color="#ff33ff">"jakarta.apache.org/tomcat/index.html"</font>); <br /></li><li>    mycustomer2.setAge(3); <br /></li><li>     <br /></li><li>    <i><font color="#339900">//客户3</font></i><br /></li><li>    Customer mycustomer3 = <b><font color="#0000ff">new</font></b> Customer(); <br /></li><li>    mycustomer3.setName(<font color="#ff33ff">"Log4J"</font>); <br /></li><li>    mycustomer3.setAddress(<font color="#ff33ff">"jakarta.apache.org/log4j/docs/index.html"</font>); <br /></li><li>    mycustomer3.setAge(2); <br /></li><li>     <br /></li><li>    <i><font color="#339900">//d到allMyCustomer(ArrayList)?</font></i><br /></li><li>    allMyCustomer.add(mycustomer1); <br /></li><li>    allMyCustomer.add(mycustomer2); <br /></li><li>    allMyCustomer.add(mycustomer3); <br /></li><li>     <br /></li><li>    <i><font color="#339900">//q个文g中设定了Velocity使用的log4j的配|和Velocity的模版文件所在的目录</font></i><br /></li><li>    Velocity.init(<font color="#ff33ff">"D:\\Template\\resource\\jt.properties"</font>); <br /></li><li>    <i><font color="#339900">//模版文g名,模版文g所在的路径在上一条语句中已经讄?/font></i><br /></li><li>    Template template =Velocity.getTemplate(<font color="#ff33ff">"hello.vm"</font>, <font color="#ff33ff">"gb2312"</font>);  <br /></li><li>    <i><font color="#339900">//实例化一个Context</font></i><br /></li><li>    VelocityContext context = <b><font color="#0000ff">new</font></b> VelocityContext();     <br /></li><li></li><li>    <i><font color="#339900">/**</font></i><br /></li><li><i><font color="#339900">     * 注意q里我们仅仅需要给一个模版变量负?/font></i><br /></li><li><i><font color="#339900">     */</font></i><br /></li><li>    context.put(<font color="#ff33ff">"allCustomer"</font>, allMyCustomer);     <br /></li><li>    <i><font color="#339900">//开始模版的替换</font></i><br /></li><li>    template.merge(context, writer); <br /></li><li></li><li>    <i><font color="#339900">//写到文g?/font></i><br /></li><li>    <font color="#ff0000">PrintWriter</font> filewriter = <b><font color="#0000ff">new</font></b><font color="#ff0000">PrintWriter</font>(<b><font color="#0000ff">new</font></b><font color="#ff0000">FileOutputStream</font>(outpath),<b><font color="#0000ff">true</font></b>); <br /></li><li>    filewriter.println(writer.toString()); <br /></li><li>    filewriter.close(); </li></ol></div>    <br />    l果Q?br /><br /><div id="r3z9rbr" class="codeStyle"><ol><li></li><li>    <<font color="#ff0000">HTML</font>> <br /></li><li>        <BODY> <br /></li><li>            <table> <br /></li><li>                <tr> <br /></li><li>                    <td>名称</td><td>地址</td><td>q龄</td> <br /></li><li>                </tr> <br /></li><li>                <tr>                 <br /></li><li>                    <td>Velocity</td> <br /></li><li>                    <td>jakarta.apache.orgvelocityindex.html</td> <br /></li><li>                    <td>2</td> <br /></li><li>                </tr> <br /></li><li>                <tr>                 <br /></li><li>                    <td>Log4J</td> <br /></li><li>                    <td>jakarta.apache.orglog4jdocsindex.html</td> <br /></li><li>                    <td>2</td> <br /></li><li>                </tr> <br /></li><li>            </table> <br /></li><li>        </BODY> <br /></li><li>    </<font color="#ff0000">HTML</font>> </li></ol></div><br />    #IF语句完成逻辑判断Q这个我想不用多说了?br />    allCustomer对象包含零个或者多个Customer对象。由于ArrayList(List,HashMap,HashTable,Iterator,Vector{?属于Java Collections Framework的一部分Q我们可以用#foreach指oq代其内宏V我们不用担心如何定型对象的cd——映像引擎会为我们完成这个Q务?foreach指o的一般格式是?foreach in ”?foreach指oq代listQ把list中的每个元素攑օitem参数Q然后解?foreach块内的内宏V对于list内的每个元素Q?foreach块的内容都会重复解析一ơ。从效果上看Q它相当于告诉模板引擎说Q“把list中的每一个元素依ơ放入item变量Q每ơ放入一个元素,输出一?foreach块的内容”?br />    <br />    MVC设计模型Q?br />    使用模板引擎最大的好处在于Q它分离了代码(或程序逻辑Q和表现Q输出)。由于这U分,你可以修改程序逻辑而不必担心邮件消息本w;cM圎ͼ你(或公关部门的职员Q可以在不重新编译程序的情况下,重新~写客户列表?实际上,我们分离了系l的数据模式QData ModelQ即提供数据的类Q、控制器QControllerQ即客户列表E序Q以及视图(ViewQ即模板Q。这U三层体pȝ为Model-View-Controller模型QMVCQ。如果遵从MVC模型Q代码分成三个截然不同的层,化了软g开发过E中所有相关h员的工作?l合模板引擎使用的数据模式可以是MJava对象Q最好是使用Java Collection Framework的对象。控制器只要了解模板的环境(如VelocityContextQ,一般这U环境都很容易用。一些关pL据库的“对?关系”映工兯够和模板引擎很好地协同,化JDBC操作Q对于EJBQ情形也cM?模板引擎与MVC中视图这一部分的关pL为密切。模板语a的功能很丰富、强大,以处理所有必需的视囑֊能,同时它往往很简单,不熟悉编E的Z可以使用它。模板语a不仅使得设计者从q于复杂的编E环境中解脱出来Q而且它保护了pȝQ避免了有意或无意带来危险的代码。例如,模板的编写者不可能~写出导致无限@环的代码Q或侵占大量内存的代码。不要轻估这些安全机制的价|大多数模板编写者不懂得~程Q从长远来看Q避免他们接触复杂的~程环境相当于节省了你自q旉?许多模板引擎的用L信,在采用模板引擎的Ҏ中,控制器部分和视图部分的明分,再加上模板引擎固有的安全机制Q得模板引擎以成为其他内容发布系l(比如JSPQ的替代Ҏ。因此,Java模板引擎最常见的用途是替代JSP也就不为奇了?<br />    HTML处理 Q?br />    ׃ZL看重模板引擎用来替换JSP的作用,有时他们会忘记模板还有更q泛的用途。到目前为止Q模板引擎最常见的用途是处理HTML Web内容。但我还用模板引擎生成过SQL、email、XML甚至Java源代码?br /><img src ="http://www.tkk7.com/TrampEagle/aggbug/49340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/TrampEagle/" target="_blank">TrampEagle</a> 2006-05-31 22:03 <a href="http://www.tkk7.com/TrampEagle/articles/49340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DisplayTag应用http://www.tkk7.com/TrampEagle/articles/48815.htmlTrampEagleTrampEagleMon, 29 May 2006 10:24:00 GMThttp://www.tkk7.com/TrampEagle/articles/48815.htmlhttp://www.tkk7.com/TrampEagle/comments/48815.htmlhttp://www.tkk7.com/TrampEagle/articles/48815.html#Feedback0http://www.tkk7.com/TrampEagle/comments/commentRss/48815.htmlhttp://www.tkk7.com/TrampEagle/services/trackbacks/48815.html--  作者:bibiye
--  发布旉Q?005-12-16 13:18:07

--  DisplayTag应用
DisplayTag是一个非常好用的表格昄标签Q适合MVC模式Q其主页?a target="_blank">http://displaytag.sourceforge.net  
一、最单的情况Q未使用<display:column/>标签
  <%request.setAttribute( "test", new ReportList(6) );%>
  <display:table name="test" />
  标签遍历List里的每一个对象,q将对象里的所有属性显C出来。一般用于开发的时候检查对象数据的完整性?br />  
二、?lt;display:column/>标签的情?/b>
<display:table name="test">
  <display:column property="id" title="ID" />
  <display:column property="name" />
  <display:column property="email" />
  <display:column property="status" />
  <display:column property="description" title="Comments"/>
</display:table>
   property对应List里对象的属性(用getXXX()Ҏ取得Q,title则对应表D头里的列名。定义列有两U方式:
   A?lt;display:column property="email" />
      使用<display:column/>标签里的property属性来定义
   B?lt;display:column title="email">email@it.com</display:column>
      ?lt;display:column/>标签体里增加内容Q可以是帔RQ也可以用其他标{{?br />   两种方式比较Q用property属性来定义更加快速和利于排序?br />  
三、表格显C样式的定义
  A、在<display:table/>?lt;display:column/>标签里指定标准的html属性,烦琐
  B、修Ҏ式表
<display:table name="test" class="mars">
  <display:column property="id" title="ID" class="idcol"/>
  <display:column property="name" />
  <display:column property="email" />
  <display:column property="status" class="tableCellError" />
  <display:column property="description" title="Comments"/>
</display:table>
   通过class属性来指定所要应用的样式。可以在光认样式表里(./css/screen.cssQ直接修?br />  
四、标{֏得数据的数据?br />  有四U范?br />   pageScope
   requestScope (默认)  <display:table name="test2" >
   sessionScope  <display:table name="sessionScope.holder.list" > 注意Q这里要指定范围Q非默认
   applicationScope
  
五、通过增加id属性创建隐含的对象
<display:table name="test" id="testit">
    <display:column property="id" title="ID" />
    <display:column property="name" />
    <display:column title="static value">static</display:column>
    <display:column title="row number (testit_rowNum)"><%=pageContext.getAttribute("testit_rowNum")%></display:column>
    <display:column title="((ListObject)testit).getMoney()"><%=((ListObject)pageContext.getAttribute("testit")).getMoney()%></display:column>
</display:table>
   注意到在<display:table/>里增加了id属性,q时在page context里创Z一个隐含对象,指向List里的当前对象Q?br />   可以通过(ListObject)pageContext.getAttribute("id")来捕莯个对象。同时还创徏了一个id_rowNum对象Q同P?br />   通过pageContext.getAttribute("testit_rowNum")来捕P它仅仅代表当前行的行数?br />   有了q两个隐含对象,可以通过其他标签来访问,例如Jstl:
  <display:table id="row" name="mylist">
    <display:column title="row number" >
      <c:out value="${row_rowNum}"/>
    </display:column>
    <display:column title="name" >
      <c:out value="${row.first_name}"/>
      <c:out value="${row.last_name}"/>
    </display:column>
  </display:table>
  
六、显C部分数?/b>
   昄开始五条数据:通过讑֮length属?br /><display:table name="test" length="5">
  <display:column property="id" title="ID" />
  <display:column property="email" />
  <display:column property="status" />
</display:table>
   昄W三到第八条数据Q通过讑֮offset和length属?br /><display:table name="test" offset="3" length="5">
  <display:column property="id" title="ID" />
  <display:column property="email" />
  <display:column property="status" />
</display:table>  

七、对email和url地址的直接连?/b>
<display:table name="test" >
  <display:column property="id" title="ID" />
  <display:column property="email" autolink="true" />
  <display:column property="url" autolink="true" />
</display:table>
如果要显C的对象里包含email和url地址Q则可以在display:column里直接设定autolink="true"来直接连?br />
八、用装饰模式{换数据显C(写自q decorator Q?/b>
  A、对整个表格应用decorator
  <display:table name="test" decorator="org.displaytag.sample.Wrapper" >
      <display:column property="id" title="ID" />
      <display:column property="email" />
      <display:column property="status" />
      <display:column property="date" />
      <display:column property="money" />
  </display:table>
    org.displaytag.sample.Wrapper卌己写的decoratorQ它要承TableDecoratorc,看看它的一个方法:
        public String getMoney()
    {
        return this.moneyFormat.format(((ListObject) this.getCurrentRowObject()).getMoney());
    }
    很明显,它通过父类的getCurrentRowObject()Ҏ获得当前对象Q然后对其getMoney()Ҏq行‘a漆?br />  B、对单独的column应用decorator
  <display:table name="test">
     <display:column property="id" title="ID" />
     <display:column property="email" />
     <display:column property="status" />
     <display:column property="date" decorator="org.displaytag.sample.LongDateWrapper" />
  </display:table>
    org.displaytag.sample.LongDateWrapper要实现ColumnDecorator接口Q它的方法:
        public final String decorate(Object columnValue)
    {
        Date date = (Date) columnValue;
        return this.dateFormat.format(date);
    }
    昄Q它获得不了当前对象Q因为它实现的是接口Q,仅仅是获得该对象的columnValueQ然后‘a漆?br />    
九、创建动态连?br />   有两U方法创建动态连接:
   A、在<display:column/>里通过增加href、paramId、paramName、paramScope、paramProperty属?br />      href             基本的URL 地址
      paramId          加在URL 地址后的参数名称
      paramName        数据bean的名Uͼ一般ؓnullQ即使用当前List里的对象Q?br />      paramScope       数据bean的范_一般ؓnull
      paramProperty    数据bean的属性名Uͼ用来填充URL 地址后的参数?br /><display:table name="sessionScope.details">
  <display:column property="id" title="ID" href="details.jsp" paramId="id" />
  <display:column property="email" href="details.jsp" paramId="action" paramName="testparam" paramScope="request" />
  <display:column property="status" href="details.jsp" paramId="id" paramProperty="id" />
</display:table>  
    q种Ҏ便直接,但缺Ҏ无法产生cMdetails.jsp?id=xx&action=xx的复合URL
   B、应用decorator 创徏动态连接:
<display:table name="sessionScope.details" decorator="org.displaytag.sample.Wrapper" >
  <display:column property="link1" title="ID" />
  <display:column property="email" />
  <display:column property="link2" title="Actions" />
</display:table>
   org.displaytag.sample.Wrapper里的ҎQ?br />public String getLink1()
{
  ListObject lObject= (ListObject)getCurrentRowObject();
  int lIndex= getListIndex();
  return "<a href=\\"details.jsp?index=" + lIndex + "\\">" + lObject.getId() + "</a>";
}


public String getLink2()
{
  ListObject lObject= (ListObject)getCurrentRowObject();
  int lId= lObject.getId();

  return "<a href=\\"details.jsp?id=" + lId
   + "&action=view\\">View</a> | "
   + "<a href=\\"details.jsp?id=" + lId
   + "&action=edit\\">Edit</a> | "
   + "<a href=\\"details.jsp?id=" + lId
   + "&action=delete\\">Delete</a>";
}

十、分?br />   实现分页非常的简单,增加一个pagesize属性指定一ơ想昄的行数即?br /><display:table name="sessionScope.test" pagesize="10">
<display:column property="id" title="ID" />
<display:column property="name" />
<display:column property="email" />
<display:column property="status" />
</display:table>

十一、排?br />   排序实现也是很简单,在需要排序的column里增加sortable="true"属性,headerClass="sortable"仅仅?br />   指定昄的样式。column里的属性对象要实现Comparable接口Q如果没有的话可以应用decorator
   defaultsort="1"              默认W一个column排序
   defaultorder="descending"    默认递减排序
<display:table name="sessionScope.stest" defaultsort="1" defaultorder="descending">
  <display:column property="id" title="ID" sortable="true" headerClass="sortable" />
  <display:column property="name" sortable="true" headerClass="sortable"/>
  <display:column property="email" />
  <display:column property="status" sortable="true" headerClass="sortable"/>
</display:table>
  注意的是Q当同时存在分页时排序仅仅针对的是当前页面,而不是整个List都进行排?br />  
十二、column 分组
   分组只是需要在column里增加group属?br /><display:table name="test" class="simple">
  <display:column property="city" title="CITY" group="1"/>
  <display:column property="project" title="PROJECT" group="2"/>
  <display:column property="amount" title="HOURS"/>
  <display:column property="task" title="TASK"/>
</display:table>

十三、导出数据到其他格式Q页面溢出filter??Q?/b>
   ?lt;display:table/>里设定export="true"
   ?lt;display:column/>里设定media="csv excel xml pdf" 军_该字D在导出到其他格式时被包不包含,不设定则都包?br />   <display:setProperty name="export.csv" value="false" />
   军_该种格式能不能在面中导?br /><display:table name="test" export="true" id="currentRowObject">
  <display:column property="id" title="ID"/>
  <display:column property="email" />
  <display:column property="status" />
  <display:column property="longDescription" media="csv excel xml pdf" title="Not On HTML"/>
  <display:column media="csv excel" title="URL" property="url"/>
  <display:setProperty name="export.pdf" value="true" />
  <display:setProperty name="export.csv" value="false" />
</display:table>

十四、配|属性,覆盖默认
  两种ҎQ?br />  A、在E序classpath下新建displaytag.properties文g
  B、对于单个表|应用<display:setProperty>标签
  具体可配|的属性:http://displaytag.sourceforge.net/configuration.html
  
十五、一个完整的例子
<display:table name="test" export="true" sort="list" pagesize="8">
  <display:column property="city" title="CITY" group="1" sortable="true"    headerClass="sortable"/>
  <display:column property="project" title="PROJECT" group="2" sortable="true" headerClass="sortable"/>
  <display:column property="amount" title="HOURS"/>
  <display:column property="task" title="TASK"/>
</display:table>
   sort="list" Ҏ个listq行排序
   导出数据到其他格式时Qgroup无效

解决DisplayTag有中文条件时的分问?(转自Q?a >http://blog.donews.com/lveyo/archive/2006/04/27/848346.aspx)


很早开始用DisplayTag了,真得很方便,不用考虑分页Q表格等问题?/p>

但是有一个问题一直困扰我Q就是有中文作ؓ表单提交内容的时候,页׃能用了,中文变成了ؕ码?/p>

表单传送时Q?!--StartFragment --> form的提交采用的是PostҎQ这没错Q但链接采用的是GetҎQ问题就出在q里Q因为和Tomcat4相比QTomcat5的post和get采用的方式不再相同了Q汉字编码的实现方式也不同了?/p>

Post是将地址传送一ơ,form的数据单独提交,而Get则是地址和参C起传送,传送的不止是form的数据?br />
 默认情况下,Tomcat对请求采用的默认~码是ISO-8859-1Q?/a>q样我们提交的汉字被认ؓ是ISO-8859-1的编码,所以在E序中接收时昄q。?!--StartFragment --> 在过滤器中调用request.setCharacterEncoding("GBK")Q那么Post上来的汉字将被认为是GBK~码Q而Tomcat5对于Geth上来的编码ƈ不根据过滤器的设定L认编码方式,默认的依然是ISO-8859-1Q?a>所以,即你的面使用默认的编码方式进行编码,然后使用ISO-8859-1q行解码Q得到的l果也不?/a>?

解决ҎQ?br />在Server.xml的connector部分讑֮URIEncoding的|Ҏ~码方式指定自己的?/a>可以了
例如QURIEncoding="GB2312"



TrampEagle 2006-05-29 18:24 发表评论
]]>
EasyJWebQVelocity脚本教程http://www.tkk7.com/TrampEagle/articles/39873.htmlTrampEagleTrampEagleFri, 07 Apr 2006 08:57:00 GMThttp://www.tkk7.com/TrampEagle/articles/39873.htmlhttp://www.tkk7.com/TrampEagle/comments/39873.htmlhttp://www.tkk7.com/TrampEagle/articles/39873.html#Feedback0http://www.tkk7.com/TrampEagle/comments/commentRss/39873.htmlhttp://www.tkk7.com/TrampEagle/services/trackbacks/39873.html引自Q?a >http://www.easyjf.com/easyjweb/velocity.htm

Velocity是一个基于java的模板引擎(template engineQ。它允许MZ仅简单的使用模板语言Qtemplate languageQ来引用由java代码定义的对象?当Velocity应用于web开发时Q界面设计h员可以和javaE序开发h员同步开发一个遵循MVC架构的web站点Q也是_面设计人员可以只关注页面的昄效果Q而由javaE序开发h员关注业务逻辑~码。Velocityjava代码从web面中分d来,q样为web站点的长期维护提供了便利Q同时也为我们在JSP和PHP之外又提供了一U可选的Ҏ?

官方|站Q?a class="style1" target="_blank">http://jakarta.apache.org/velocity/

Velocity脚本摘要
1、声?#set ($var=XXX)
左边可以是以下的内容
Variable reference
String literal
Property reference
Method reference
Number literal #set ($i=1)
ArrayList #set ($arr=["yt1","t2"])
技持算术运符

2、注?
单行## XXX
多行#* xxx
xxxx
xxxxxxxxxxxx*#

References 引用的类?br />3、变?Variables
?"$" 开_W一个字W必Mؓ字母。character followed by a VTL Identifier. (a .. z
or A .. Z).
变量可以包含的字W有以下内容Q?br />alphabetic (a .. z, A .. Z)
numeric (0 .. 9)
hyphen ("-")
underscore ("_")

4、Properties
$Identifier.Identifier
$user.name
hashtable user中的的name?cMQuser.get("name")

5、Methods
object user.getName() = $user.getName()

6、Formal Reference Notation
用{}把变量名跟字W串分开

?br />#set ($user="csy"}
${user}name
q回csyname

$username
$!username
$?!的区?br />当找不到username的时候,$usernameq回字符?$username"Q?!usernameq回I字W串""

7、双引号 ?引号
#set ($var="helo")
test"$var" q回testhello
test'$var' q回test'$var'
可以通过讄 stringliterals.interpolate=false改变默认处理方式

8、条件语?br />#if( $foo )
<strong>Velocity!</strong>
#end
#if($foo)
#elseif()
#else
#end
?foo为null或ؓBoolean对象的false值执?

9、逻辑q算W?== && || !

10、@环语?foreach($var in $arrays ) // 集合包含下面三种Vector, a Hashtable or an Array
#end
#foreach( $product in $allProducts )
<li>$product</li>
#end

#foreach( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key)</li>
#end

#foreach( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
11、velocityCount变量在配|文件中定义
# Default name of the loop counter
# variable reference.
directive.foreach.counter.name = velocityCount
# Default starting value of the loop
# counter variable reference.
directive.foreach.counter.initial.value = 1

12、包含文?
#include( "one.gif","two.txt","three.htm" )

13、Parse导入脚本
#parse("me.vm" )

14?stop 停止执行q返?

15、定义宏Velocimacros ,相当于函?支持包含功能
#macro( d )
<tr><td></td></tr>
#end
调用
#d()

16、带参数的宏
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end

17、Range Operator
#foreach( $foo in [1..5] )

Velocity用户手册---中文?(来源|络)

Velocity是什么?

Velocity是一个基于java的模板引擎(template engineQ。它允许MZ仅简单的使用模板语言Qtemplate languageQ来引用由java代码定义的对象?

当Velocity应用于web开发时Q界面设计h员可以和javaE序开发h员同步开发一个遵循MVC架构的web站点Q也是_面设计人员可以只关注页面的昄效果Q而由javaE序开发h员关注业务逻辑~码。Velocityjava代码从web面中分d来,q样为web站点的长期维护提供了便利Q同时也为我们在JSP和PHP之外又提供了一U可选的Ҏ?

Velocity的能力远不止web站点开发这个领域,例如Q它可以从模板(templateQ生SQL和PostScript、XMLQ它也可以被当作一个独立工h产生源代码和报告Q或者作为其他系l的集成lg使用。Velocity也可以ؓTurbine web开发架构提供模板服务(template serviceQ。Velocity+Turbine提供一个模板服务的方式允许一个web应用以一个真正的MVC模型q行开发?

Velocity能ؓ我们作什么?

The Mud Store Example

假设你是一家专门出售Mud的在U商店的面设计人员Q让我们暂且U它为“在UMUD商店”。你们的业务很旺Q客户下了各U类型和数量的mud订单。他们都是通过输入用户名和密码后才登陆C的网站,登陆后就允许他们查看订单q购买更多的mud。现在,一U非常流行的mud正在打折销售。另外有一些客戯律性的购买另外一U也在打折但是不是很行的Bright Red MudQ由于购买的人ƈ不多所以它被安|在面的边~。所有用L信息都是被跟tƈ存放于数据库中的Q所以某天有一个问题可能会冒出来:Z么不使用velocity来用户更好的浏览他们感兴趣的商品呢Q?

Velocity使得web面的客户化工作非常Ҏ。作Z个web site的设计h员,你希望每个用L陆时都拥有自q面?

你会见了一些公司内的Y件工E师Q你发现他们每个人都同意客户应该拥有h个性化的信息。那让我们把软g工程师应该作的事情发在一边,看一看你应该作些什么吧?

你可能在面内嵌套如下的VTL声明Q?

<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?

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何事情?

Q字W后紧跟一个directiveQsetӞq个set directive使用一个表辑ּQ用括号封闭)――一个方E式分配一个值给变量。变量被列在左边Q而它的D列在双Q最后他们之间用=号分剌Ӏ?

在上面的例子中,变量?aQ而它的值是Velocity。和其他的references一样以$字符开始,而值L以双引号闭。Velocity中仅有String可以被赋值给变量?

C以下的规则:

使用$字符开始的references用于得到什么;使用#字符开始的directives用于作些什么?

Hello Velocity World!

一旦某个变量被分配了一个|那么你就可以在HTML文g的Q何地方引用它。在下面的例子中Q一个D分配l?foo变量Qƈ在其后被引用?

<html>

<body>

#set ( $foo = “Velocity?)

Hello $foo World!

</body>

</html>

上面的实现结果是在页面上打印“Hello Velocity WorldQ?

Z使包含VTL directives的statement更具有可L,我们鼓励你在新行开始每个VTL statementQ尽你不是必须q么作。Set directive在后面详细描述?

注释

单行注释Q?

## This is a single line comment.

多行注释Q?

#*

Thus begins a multi-line comment. Online visitors won't

see this text because the Velocity Templating Engine will

ignore it.

*#

文档格式Q?

#**

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中用它们?

Everything coming to and from a reference被作Z个String对象处理。如果有一个对?foo是一个Integer对象Q那么Velocity调用它的toString()Ҏ这个对象{型ؓStringcd?

变量

格式要求同java?

属?

例子Q?

$customer.Address

$purchase.Total

$customer.Address有两U含义。它可以表示Q查找hashtable对象customer中以Address为关键字的|也可以表C用customer对象的getAddress()Ҏ。当你的面被请求时QVelocity确定以上两U方式选用那种Q然后返回适当的倹{?

Ҏ

一个方法就是被定义在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ȝ话,那你是正的?

VTL属性可以作为VTLҎ的羃写?customer.Address属性和使用$customer.getAddress()Ҏh相同的效果。如果可能的话用属性的方式是比较合理的。属性和Ҏ的不同点在于你能够给一个方法指定一个参数列表?

正式reference标记

reference的正是格式如下:

${mudSlinger}变量

${customer.Address}属?

${purchase.getTotal()}Ҏ

非正是格式更见常用,但是有时q是使用正是格式比较适合。例如:你希望通过一个变?vice来动态的l织一个字W串?

Jack is a $vicemaniac.

本来变量?vice现在却变成了$vicemaniacQ这样Veloctiy׃知道您到底要什么了。所以,应该使用正是格式书写

Jack is a ${vice}maniac

现在Velocity知道变量?vice而不?vicemaniac?

Quiet reference notation

例如Q?

<input type=”text?name=”email?value=?email?/>

当页面的form被初始加载时Q变?emailq没有|q时你肯定是希望它能够显CZ个blank text来代替输出?email”这L字段。那么用quiet reference notation比较合适?

<input type=”text?name=”email?value=?!email?>

q样文本框的初始值就不会是email而是Ig?

正式和quiet格式的reference notation也可一同用,像下面这P

<input type=”text?name=”email?value=?!{email}?>

Getting literal

Velocity使用Ҏ字符$?来帮助它工作Q所以如果要在template里用这些特D字W要格外心。本节将讨论$字符?

货币字符

在VTL中?2.5q样的货币标识是没有问题得的QVTL不会它错认为是一个referenceQ因为VTL中的referenceL以一个大写或者小写的字母开始?

Escaping valid VTL reference

VTL中用“\\”作为逃逸符?

例如Q?

#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?

$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实例变量?

Directives

Reference允许设计者用动态的内容Q而directive使得你可以应用java代码来控制你的显C逻辑Q从而达C所期望的显C效果?

#set

#set directive被用于设|一个reference的倹{例如:

#set ( $primate = “monkey?)

#set ( $customer.Behavior = $primate )

赋值左侧的QLHSQ必L一个变量或者属性reference。右侧(RHSQ可以是以下cd中一U:

l变量reference

lString literal

l属性reference

lҎreference

lnumber literal

lArrayList

下面是应用各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回一个“bill”,?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

在上面的例子中,E序不能智能的Ҏ$result的值决定查询是否成功。在$result?set后(added to the contextQ,它不能被讄回nullQremoved from the contextQ。打印的l果显CZơ查询结果都成功了,但是实际上有一个查询是p|的?

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闭在一对双引号内?

#set ( $directoryRoot = “www?)

#set ( $templateName = “index.vm?)

#set ( $template = ?directoryRoot/$tempateName?)

$template

上面q段代码的输出结果ؓQwww/index.vm

但是Q当string literal被封装在单引号内Ӟ它将不被解析Q?

#set ( $foo = “bar?)

$foo

#set ( $blargh = ?foo' )

l果Q?

bar

$foo

上面q个Ҏ可以通过修改velocity.properties文g的stringliterals.interpolate = false的值来改变上面的特性是否有效?

条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所以当我们说“boolean”时实际上代表的时一个Boolean对象。即便某个方法返回的是一个boolean|Velocity也会利用内省机制它转换Z个Boolean的相同倹{?

如果条g成立Q那?if?end之间的内容将被显C?

#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不同它用“=Q”来比较两个|而且velocity要求{号两边的值类型相同?

关系、逻辑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?

<ul>

#foreach ( $product in $allProducts )

<li> $product </li>

#end

</ul>

每次循环$allProducts中的一个值都会赋l?product变量?

$allProducts可以是一个Vector、Hashtable或者Array。分配给$product的值是一个java对象Qƈ且可以通过变量被引用。例如:如果$product是一个java的Productc,q且q个产品的名字可以通过调用他的getNameQ)Ҏ得到?

现在我们假设$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?”开始,但是你可以在velocity.properties讄它是从?”还是从?”开始。下面就是文件中的配|:

# 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目录下?

#inclued ( “one.txt?)

如果您需要引入多个文Ӟ可以用逗号分隔pQ?

#include ( “one.gif? “two.txt? “three.htm?)

在括号内可以是文件名Q但是更多的时候是使用变量的:

#inclue ( “greetings.txt? $seasonalstock )

parse

#parse script element允许模板设计者一个包含VTL的本地文件。Velocity解析其中的VTLqrender模板?

#parse( “me.vm?)

像#includeQ?parse接受一个变量而不是一个模ѝQ何由#parse指向的模杉K必须包含在TEMPLATE_ROOT目录下。与#include不同的是Q?parse只能指定单个对象?

你可以通过修改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?

$count

#set ( $count = $count ?1 )

#if ( $count > 0 )

#parse( “parsefoo.vm?)

#else

All done with parsefoo.vm!

#end

的显C结果ؓQ?

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是很有帮助的?

#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()?

每个Velocimacro可以拥有L数量的参数――甚?个参敎ͼ虽然定义时可以随意设|参数数量,但是调用q个Velocimacro时必L定正的参数。下面是一个拥有两个参数的VelocimacroQ一个参数是color另一个参数是arrayQ?

#macro ( tablerows $color $somelist )

#foreach ( $something in $somelist )

<tr><td bgcolor=$color>$something</td</tr>

#end

#end

调用#tablerows VelocimacroQ?

#set ( $greatlakes = [ “Superior? “Michigan? “Huron? “Erie? “Ontario?] )

#set ( $color = “blue?)

<table>

#tablerows( $color $greatlakes )

</table>

l过以上的调用将产生如下的显C结果:

<table>

<tr><td bgcolor=?blue?gt; Superior </td></tr>

<tr><td bgcolor=?blue?gt; Michigan </td></tr>

<tr><td bgcolor=?blue?gt; Huron </td></tr>

<tr><td bgcolor=?blue?gt; Erie </td></tr>

<tr><td bgcolor=?blue?gt; Ontario </td></tr>

</table>

Velocimacros可以在Velocity模板内实现行内定义(inlineQ,也就意味着同一个web site内的其他Velocity模板不可以获得Velocimacros的定义。定义一个可以被所有模板共享的Velocimacro昄是有很多好处的:它减了在一大堆模板中重复定义的数量、节省了工作旉、减了出错的几率、保证了单点修改?

上面定义?tablerows( $color $list )Velocimacro被定义在一个Velocimacros模板?在velocity.properties中定?里,所以这个macro可以在Q何规范的模板中被调用。它可以被多ơ应用ƈ且可以应用于不同的目的。例如下面的调用Q?

#set ( $parts = [ “volva? “stipe? “annulus? “gills? “pileus?] )

#set ( $cellbgcol = ?CC00FF?)

<table>

#tablerows( $cellbgcol $parts )

</table>

上面VTL生如下的输出Q?

<table>

<tr><td bgcolor=?CC00FF?gt; volva </td</tr>

<tr><td bgcolor=?CC00FF?gt; stipe </td</tr>

<tr><td bgcolor=?CC00FF?gt; annulus </td</tr>

<tr><td bgcolor=?CC00FF?gt; gills </td</tr>

<tr><td bgcolor=?CC00FF?gt; pileus </td</tr>

</table>

Velocimacro arguments

Velocimacro可以使用以下M元素作ؓ参数Q?

lReferenceQQ何以$开头的reference

lString literalQ?

lNumber literalQ?

lIntegerRangeQ[1?3]或者[$foo?$bar]

l对象数组Q[“a?”b?”c”]

lboolean|true、false

当将一个reference作ؓ参数传递给VelocimacroӞh意reference作ؓ参数时是以名字的形式传递的。这意味着参数的值在每次Velocimacro内执行时才会被生。这个特性得你可以一个方法调用作为参C递给VelocimacroQ而每ơVelocimacro执行旉是通过q个Ҏ调用产生不同的值来执行的。例如:

#macro ( callme $a )

$a $a $a

#end

#callme( $foo.bar() )

执行的结果是Qreference $foo的barQ)Ҏ被执行了三次?

如果你不需要这LҎ可以通过以下ҎQ?

#set ( $myval = $foo.bar() )

#callme ( $myval )

Velocimacro properties

Velocity.properties文g中的某几行能够Velocimacros的实现更加灵zR注意更多的内容可以看Developer Guide?

Velocity.properties文g中的velocimacro.libraaryQ一个以逗号分隔的模板库列表。默认情况下Qvelocity查找唯一的一个库QVM_global_library.vm。你可以通过配置q个属性来指定自己的模板库?

Velocity.properties文g中的velocimacro.permissions.allow.inline属性:有两个可选的值true或者falseQ通过它可以确定Velocimacros是否可以被定义在regular template内。默认值是ture――允许设计者在他们自己的模板中定义Velocimacros?

Velocity.properties文g中的

velocimacro.permissions.allow.inline.replace.global属性有两个可选值true和falseQ这个属性允怋用者确定inline的Velocimacro定义是否可以替代全局Velocimacro定义Q比如在velocimacro.library属性中指定的文件内定义的VelocimacroQ。默认情况下Q此gؓfalse。这样就L本地Velocimacro定义覆盖全局定义?

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?

Velocity.properties文g中的velocimacro.context.localscope属性有true和false两个可选|默认gؓfalse。当讄为trueӞM在Velocimacro内通过#set()对context的修改被认ؓ是针Ҏvelocimacro的本地设|,而不会永久的影响内容?

Velocity.properties文g中的velocimacro.library.autoreload属性控制Velocimacro库的自动加蝲。默认是false。当讄为tureӞ对于一个Velocimacro的调用将自动查原始库是否发生了变化,如果变化重新加载它。这个属性得你可以不用重新启动servlet容器而达到重新加载的效果Q就像你使用regular模板一栗这个属性可以用的前提是resource loader~存是off状态(file.resource.loader.cache = falseQ。注意这个属性实际上是针对开发而非产品的?

Velocimacro Trivia

Velocimacro必须被定义在他们被用之前。也是_你的#macro()声明应该出现在用Velocimacros之前?

特别要注意的是,如果你试?parse()一个包?macro()的模ѝ因?parse()发生在运行期Q但是解析器在parsetiem军_一个看似VM元素的元素是否是一个VM元素Q这?parse()-ing一lVM声明不按照预期的样子工作。ؓ了得到预期的l果Q只需要你单的使用velocimacro.library使得Velocity在启动时加蝲你的VMs?

Escaping VTL directives

VTL directives can be escaped with “\\”号Q用方式跟VTL的reference使用逃逸符的格式差不多?

## #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?

\\#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?

\\ Vyacheslav Ganelin

\\

但是如果$jazz为falseQ那么将没有输出。(书上说会没有输出Q但是我觉得应该q有有“\\”字W被输出。)

VTLQFormatting issues

管在此用户手册中VTL通常都开始一个新行,如下所C:

#set ( $imperial = [ “Munetaka? “Koreyasu? “Hisakira? “Morikune?] )

#foreach ( $shogun in $imperial )

$shogun

#end

但是像下面这U写法也是可以的Q?

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.

或?

Send me

#set($foo = [?10 and ?”a cake”])

#foreach Q?a in $foo Q?a

#end please.

q两U的输出l构一栗?

其他Ҏ和杂项

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果?

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?

First exampleQ?

1 2 3 4 5

Second exampleQ?

2 1 0 -1 -2

Third exampleQ?

0 1

Fourth exampleQ?

[1..3]

注意Qrange operator只在#set?foreach中有效?

Advanced IssueQEscaping andQ?

当一个reference被“!”分隔时Qƈ且在它之前有逃逸符Ӟreference以Ҏ的方式处理。注意这U方式与标准的逃逸方式时不同的。对照如下:

#set ( $foo = “bar?)

Ҏ形式标准格式

Render前Render后Render前Render?

$\\!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是不合法的?

但是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?

#set ( $color = $bar.rowColor() )

#foo ( $color )

can I register velocimacros via #parse()?

目前QVelocimacros必须在第一ơ被模板调用前被定义。这意味着你的#macro()声明应该出现在用Velocimacros之前?

如果你试?parse()一个包?macro() directive的模板,q一Ҏ需要牢记的。因?parse()发生在运行期Q但是解析器在parsetiem军_一个看似VM元素的元素是否是一个VM元素Q这?parse()-ing一lVM声明不按照预期的样子工作。ؓ了得到预期的l果Q只需要你单的使用velocimacro.library使得Velocity在启动时加蝲你的VMs?

What is velocimacro autoreloadingQ?

velocimacro.library.autoreload是专门ؓ开发而非产品使用的一个属性。此属性的默认值是false?

String concatenation

开发h员最帔R的问题是我如何作字符拼接Q在java中是使用“+”号来完成的?

在VTL里要惛_现同L功能你只需要将需要联合的reference攑ֈ一起就行了。例如:

#set ( $size = “Big?)

#set ( $name = “Ben?)

The clock is $size$name.

输出l果是QThe clock is BigBen.。更有趣的情冉|Q?

#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?



TrampEagle 2006-04-07 16:57 发表评论
]]>
lucene全文索实现流E?/title><link>http://www.tkk7.com/TrampEagle/articles/31642.html</link><dc:creator>TrampEagle</dc:creator><author>TrampEagle</author><pubDate>Mon, 20 Feb 2006 06:31:00 GMT</pubDate><guid>http://www.tkk7.com/TrampEagle/articles/31642.html</guid><wfw:comment>http://www.tkk7.com/TrampEagle/comments/31642.html</wfw:comment><comments>http://www.tkk7.com/TrampEagle/articles/31642.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/TrampEagle/comments/commentRss/31642.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/TrampEagle/services/trackbacks/31642.html</trackback:ping><description><![CDATA[引自Q?a >http://www.gamvan.com/developer/java/opener/2005/12/846.html</a><br /><br />对于lucene全文索,可以U地看看它的7个主要类Q这7个类同时也表达了处理全文索的7个意c因为数据库比较Zh所熟悉Q它又与全文索某些理忉|为相|所以在对下面的概念说明Ӟ会大量在渗入数据库和全文检索间的类比?<br />1QDocument Q它的中文意思是文档Q对于一个文档,通常都包括它的标题、时间、作者、内宏V如果让它的意思泛化,它也有文件的意思(怿Lucene的作者在取这个类名的时候也是经q再三斟酌的Q,对于文gQ它可以指一个TXT文本、一个HTML|页、一个PDF文g{等。总而言之,它是映射着某一个具体的文gQ这是它的单位_度。对应于<a target="_blank"><font color="#002c99">数据?/font></a>的概忉|记录Q英文是RecordQweblucene在烦引源的xml中就原原本本地采用了q个概念Q可参照<weblucene_home>/dump/blog.xml ?<br /><br />2QField Q中文意思是字段。汉语的译这个单词的意思表辑־更恰如其分了Q意思是文字片段Q它可以是一个或多个字。字D|文档QDocumentQ的ơ粒度单位,也是索的最基本单位。注意这个概念跟在搜索引擎的输入框中随意输入的那几个字或几组字不是一LQ在搜烦输入框中输入的那些文字首先需要经q一个QueryParserQ这也是7个类中的一个)其分解成真正的Field??a target="_blank"><font color="#002c99">数据?/font></a>中本来就有Field q个概念Q它xRecord的次U单位。在<a target="_blank"><font color="#002c99">数据?/font></a>一条或多条记录怎么被找出来的,往往q由对Field的检索而得来。在全文索中Document的最l取得也是差不多Q它是根据现在的某个Filed来决定的。即Ҏ文档中的某些q不完整的东西牵引出它的所需的全部?<br />CZ代码Q?<br /><table style="BORDER-TOP-WIDTH: 1px; BORDER-LEFT-WIDTH: 1px; BORDER-BOTTOM-WIDTH: 1px; BORDER-RIGHT-WIDTH: 1px" bordercolor="#e0e0e0" cellspacing="1" cellpadding="4" width="95%" align="center" border="1" table-layout:="" fixed=""><tbody><tr><td style="HEIGHT: 25px; WORD-WRAP: break-word" valign="top" bgcolor="#f6f6f6"><font style="COLOR: #b0b0b0">代码内容</font><br />[com.chedong.weblucene.search.WebLuceneResultSetTest] <br />Document doc = new Document(); <br />doc.add(Field.Keyword("keyword", "房地?)); <br />doc.add(Field.Keyword("keyword", "非典")); </td></tr></tbody></table><br />3QIndexWriter Q烦引书写?<br />CZ代码Q?<br />[org.apache.lucene.index.TestIndexWriter] <br /><table style="BORDER-TOP-WIDTH: 1px; BORDER-LEFT-WIDTH: 1px; BORDER-BOTTOM-WIDTH: 1px; BORDER-RIGHT-WIDTH: 1px" bordercolor="#e0e0e0" cellspacing="1" cellpadding="4" width="95%" align="center" border="1" table-layout:="" fixed=""><tbody><tr><td style="HEIGHT: 25px; WORD-WRAP: break-word" valign="top" bgcolor="#f6f6f6"><font style="COLOR: #b0b0b0">代码内容</font><br />Document doc = new Document(); <br />doc.add(Field.UnStored("content", "aaa")); <br />try { <br />IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true); <br />writer.addDocument(doc); <br />} <br />catch (IOException e) { <br />e.printStackTrace(); <br />} </td></tr></tbody></table><br />它的构造器new IndexWriter(dir, new WhitespaceAnalyzer(), true) 有三个参敎ͼ分别是Directory对象、分析器对象Q这是下一个要介绍的类Q和一个布量Q是否要重写索引是p个布量标明的,如果取false则仅仅是烦引附加上来?<br /><br />4QAnalyzer Q?分析器,它将目录中的一l原始文件分析成׃lDocument和它相应的次U粒度Fieldl成的烦引。因Z同的文gcdQ同L文本其内部文件流l织形式是不一LQ所以需要不同的分析器处理不同的文gcdQ如PDFAnalyzer、HtmlAnalyzerQ。又因ؓ不同的文字语a处理Field拆分QTokenQ上是不一LQ所以在语言角度上又有另一层分析器的类别区分,如下面这行代码是处理普通中文字W的 <br />[com.chedong.weblucene.search.WebLuceneResultSetTest] <br />IndexWriter writer = new IndexWriter(dir, new CJKAnalyzer(), true); <br /><br />5QQueryParser Q这前面在区分Field和用戯入的搜烦关键字时已经提及了。(它所用的词是QueryQ跟<a target="_blank"><font color="#002c99">数据?/font></a>所用的是一个概늚Q这个词同样的检索上让h感觉没有像Search那么费尽心思去q。)QueryParserq没有实际地d查询工作Q它只是ParserQ剖析)用户输入的东西,q把剖析的结果以一U规则的形式送给SearcherL行一个真正的搜烦。作为剖析的l果Q不仅仅是FieldQ还有Field们相互间的关p?termsQ譬如逻辑和ANDQ逻辑或ORQ?逻辑非NOT)?<br /><br />6QSearcher Q?搜烦一个QueryQ将l果q回?<br />[org.apache.lucene.search..TestNot] <br /><table style="BORDER-TOP-WIDTH: 1px; BORDER-LEFT-WIDTH: 1px; BORDER-BOTTOM-WIDTH: 1px; BORDER-RIGHT-WIDTH: 1px" bordercolor="#e0e0e0" cellspacing="1" cellpadding="4" width="95%" align="center" border="1" table-layout:="" fixed=""><tbody><tr><td style="HEIGHT: 25px; WORD-WRAP: break-word" valign="top" bgcolor="#f6f6f6"><font style="COLOR: #b0b0b0">代码内容</font><br />RAMDirectory store = new RAMDirectory(); <br />IndexWriter writer = new IndexWriter(store, new SimpleAnalyzer(), true); <br /><br />Document d1 = new Document(); <br />d1.add(Field.Text("field", "a b")); <br /><br />writer.addDocument(d1); <br />writer.optimize(); <br />writer.close(); <br /><br />Searcher searcher = new IndexSearcher(store); <br />Query query = QueryParser.parse("a NOT b", "field", new SimpleAnalyzer()); <br />//System.out.println(query); <br />Hits hits = searcher.search(query); </td></tr></tbody></table><br />对于每一个搜索器对象Q它都需要指定一个烦引文件\径,然后由搜索器对Query对象执行查询?上面的这个类袖珍地对7个主要类都均有涉及?<br /><br />7QHits Q?Lucene的类注释是:A ranked list of documents, used to hold search results. 搜烦的结果不仅仅是一些文档,而且q些文档q是有别的Q这个别是对于先后ơ序而言的。它对应?a target="_blank"><font color="#002c99">数据?/font></a>中的RecordSet / ResultSet ?<br /><img src ="http://www.tkk7.com/TrampEagle/aggbug/31642.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/TrampEagle/" target="_blank">TrampEagle</a> 2006-02-20 14:31 <a href="http://www.tkk7.com/TrampEagle/articles/31642.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene中文分词的高亮[highlight]昄http://www.tkk7.com/TrampEagle/articles/31641.htmlTrampEagleTrampEagleMon, 20 Feb 2006 06:30:00 GMThttp://www.tkk7.com/TrampEagle/articles/31641.htmlhttp://www.tkk7.com/TrampEagle/comments/31641.htmlhttp://www.tkk7.com/TrampEagle/articles/31641.html#Feedback0http://www.tkk7.com/TrampEagle/comments/commentRss/31641.htmlhttp://www.tkk7.com/TrampEagle/services/trackbacks/31641.htmlhttp://www.gamvan.com/developer/java/opener/2005/12/849.html

1、问题的来源 增加分词以后l果的准度提高了,但是用户反映q回l果的速度很慢。原因是Q?Lucene 做每一文档的相关关键词的高亮昄Ӟ在运行时执行了很多遍的分词操作。这样降低了性能?br />2 、解x?
?Lucene1.4.3 版本中的一个新功能可以解决q个问题?Term Vector 现在支持保存 Token.getPositionIncrement() ?Token.startOffset() 以及 Token.endOffset() 信息。利?Lucene 中新增加?Token 信息的保存结果以后,׃需要ؓ了高亮显C在q行时解析每文档。通过 Field Ҏ控制是否保存该信息。修?HighlighterTest.java 的代码如下:

代码内容
// 增加文档时保?Term 位置信息?
private void addDoc(IndexWriter writer, String text) throws IOException
{
Document d = new Document();
//Field f = new Field(FIELD_NAME, text, true, true, true);
Field f = new Field(FIELD_NAME, text , 
Field.Store.YES, Field.Index.TOKENIZED,
Field.TermVector.WITH_POSITIONS_OFFSETS);
d.add(f);
writer.addDocument(d); 
 }
// 利用 Term 位置信息节省 Highlight 旉?
void doStandardHighlights() throws Exception
{
  ?Highlighter highlighter =new Highlighter(this,new QueryScorer(query));
highlighter.setTextFragmenter(new SimpleFragmenter(20));
for (int i = 0; i < hits.length(); i++)
{
String text = hits.doc(i).get(FIELD_NAME);
int maxNumFragmentsRequired = 2;
String fragmentSeparator = "...";
TermPositionVector tpv = (TermPositionVector)reader.getTermFreqVector(hits.id(i),FIELD_NAME);
?/ 如果没有 stop words 去除q可以改?TokenSources.getTokenStream(tpv,true); q一步提速?
 ?TokenStream tokenStream=TokenSources.getTokenStream(tpv);
 ?//analyzer.tokenStream(FIELD_NAME,new StringReader(text));
 ?String result =
 ?highlighter.getBestFragments(
? tokenStream,
 ?text,
 ?maxNumFragmentsRequired, 
       fragmentSeparator);
 ?System.out.println(" " + result);
 }
}

最后把 highlight 包中的一个额外的判断L。对于中文来说没有明昄单词界限Q所以下面这个判断是错误的:

tokenGroup.isDistinct(token)

q样中文分词׃会媄响到查询速度了?


TrampEagle 2006-02-20 14:30 发表评论
]]>
Prototype Meets Ruby: A Look at Enumerable, Array and Hashhttp://www.tkk7.com/TrampEagle/articles/30260.htmlTrampEagleTrampEagleSat, 11 Feb 2006 06:04:00 GMThttp://www.tkk7.com/TrampEagle/articles/30260.htmlhttp://www.tkk7.com/TrampEagle/comments/30260.htmlhttp://www.tkk7.com/TrampEagle/articles/30260.html#Feedback0http://www.tkk7.com/TrampEagle/comments/commentRss/30260.htmlhttp://www.tkk7.com/TrampEagle/services/trackbacks/30260.html

Encytemedia

A LOOK AT SOFTWARE DEVELOPMENT, DESIGN, AND OTHER RANDOM BITS.

Working With Events In Prototype

February 08, 2006

Events drive interaction for almost everything and the web is no exception. In the style of my last article on Prototype, lets take a code-heavy look at how Prototype lets us work with events.

NOTE: This article uses Prototype 1.5.0_pre0

Basic event handling

The syntax for working with events looks like the code below.

Event.observe(element, name, observer, [useCapture]);

Assuming for a moment that we want to observe when a link was clicked, we could do the following:

// <a id="clicker" href="http://foo.com">Click me</a>
Event.observe('clicker', 'click', function(event){ alert('clicked!');});

If we wanted to get the element that fired the event, we'd do this:

Event.observe('clicker', 'click', function(event){ alert(Event.element(event));});

Observing keystrokes

If we wanted to observe keystrokes for the entire document, we could do the following:

Event.observe(document, 'keypress', function(event){ if(event.keyCode == Event.KEY_TAB) alert('Tab Pressed');});

And lets say we wanted to keep track of what has been typed into your snazzy live-search box:

Event.observe('search', 'keypress', function(event) { Element.update('search-results', $F(Event.element(event)));});

Prototype defines properties inside the event object for some of the more common keys, so feel free to dig around in Prototype to see which ones those are.

A final note on keypress events; If you'd like to detect a left click you can use Event.isLeftClick(event).

Getting the coordinates of the mouse pointer

Drag and drop, dynamic element resizing, games, and much more all require the ability to track the X and Y location of the mouse. Prototype makes this fairly simple. The code below tracks the X and Y position of the mouse and spits out those values into an input box named mouse.

   Event.observe(document, 'mousemove', function(event){$('mouse').value = "X: " + Event.pointerX(event) + "px Y: " + Event.pointerY(event) + "px";});

If we wanted to observe the mouse location when it was hovering over a certain element, we'd just change the document argument to the id or element that was relevant.

Stopping Propagation

Event.stop(event) will stop the propagation of an event but there is a bug in Safari 2.0.3 that causes this to behave unexpectedly. Ryan from Particletree has posted an in-depth article on Event.stop with a workaround for Safari.

The good news is that this bug is fixed in the Webkit version of Safari. You can check out this test in Safari 2.0.3 and Webkit to see the results of both.

Events, Binding, and Objects

Everything has been fairly straight forward so far, but things start getting a little tricker when you need to work with events in and object-oriented environment. You have to deal with binding and funky looking syntax that might take a moment to get your head around.

Lets look at some code so you can get a better understanding of what I'm talking about.

EventDispenser = Class.create();
EventDispenser.prototype = {
  initialize: function(list) {
    this.list = list;

    // Observe clicks on our list items     
    $$(this.list + " li").each(function(item) {
      Event.observe(item, 'click', this.showTagName.bindAsEventListener(this));
    }.bind(this));

    // Observe when a key on the keyboard is pressed. In the observer, we check for 
    // the tab key and alert a message if it is pressed.
    Event.observe(document, 'keypress', this.onKeyPress.bindAsEventListener(this));

    // Observe our fake live search box.  When a user types something into the box, 
    // the observer will take that value(-1) and update our search-results div with it.
    Event.observe('search', 'keypress', this.onSearch.bindAsEventListener(this));

    Event.observe(document, 'mousemove', this.onMouseMove.bindAsEventListener(this));
  },


  // Arbitrary functions to respond to events
  showTagName: function(event) {
    alert(Event.element(event).tagName);
  },


  onKeyPress: function(event) {
    var code = event.keyCode;
    if(code == Event.KEY_TAB) alert('Tab key was pressed');
  },

  onSearch: function(event) {
    Element.update('search-results', $F(Event.element(event)));
  },

  onMouseMove: function(event) {
    $('mouse').value = "X: " + Event.pointerX(event) + "px Y: " + Event.pointerY(event) + "px";
  }

}

Whoa! What's going on here? Well, we've defined our a custom class EventDispenser. We're going to be using this class to setup events for our document. Most of this code is a rewrite of the code we looked at earlier except this time, we are working from inside an object.

View a live example of our document

Looking at the initialize method, we can really see how things are different now. Take a look at the code below:

    // Observe clicks on our list items     
    $$(this.list + " li").each(function(item) {
      Event.observe(item, 'click', this.showTagName.bindAsEventListener(this));
    }.bind(this));

We've got iterators, binding and all sorts of stuff going on. Lets break down what this chunk of code is doing.

First we are hunting for a collection of elements based on it's css selector. This uses the new Prototype selector function $$. After we've found the list items we are dealing with we send those into an each iteration where we will add our observers.

Event.observe(item, 'click', this.showTagName.bindAsEventListener(this));

Now looking at the code above, you'll notice the bindAsEventListener function. This takes the method before it showTagName and treats it as the method that will be triggered when, in this case, someone clicks one of our list items.

You'll also notice we pass this as an argument to the bindAsEventListener function. This simply allows us to reference the object in context EventDispenser inside our function showTagName.

NOTE: If you prefer the jargon packed explanation of bindAsEventListener, see the Script.aculo.us wiki.

Moving on, you'll see bind(this) attached to our iterator function. This really has nothing to do with events, it is only here to allow me to use this inside the iterator. If we didn't use bind(this), I couldn't reference the method showTagName inside the iterator.

Ok, so we'll move on to looking at our methods that actually get called when an event occurs. Since we've been dealing with showTagName, lets look at it.

  showTagName: function(event) {
    alert(Event.element(event).tagName);
  }

As you can see, this function accepts one argument--the event. In order for us to get the element which fired the event we need to pass that argument to Event.element. Now we can manipulate it at will.

This covers the most confusing parts of our code. The text above is also relevant to the remaining parts of our code. If there is anything about this you don't understand, feel free to say so.

Removing Event Listeners

This one threw me for a loop the first time I tried to use it. I tried something similar to what I did in the Event.observe call with the exception of using stopObserving, but nothing seemed to change. In other words, the code below does NOT work.

$$(this.list + " li").each(function(item) {
  Event.stopObserving(item, 'click', this.showTagName);
}.bind(this));

What's the deal here? The reason this doesn't work is because there is no pointer to the observer. This means that when we passed this.showTagName in the Event.observe method before hand, we passed it as an anonymous function. We can't reference an anonymous function because it simply doesn't have a pointer.

So how do we get the job done? All we need to do is give the observing function a pointer, or the jargon free version: Set a variable that points to this.showTagName. Ok, lets change our code a bit.

this.showTagObserver = this.showTagName.bindAsEventListener(this);

// Observe clicks on our list items     
$$(this.list + " li").each(function(item) {
  Event.observe(item, 'click', this.showTagObserver);
}.bind(this));

Now we can remove the event listeners from our list like this:

$$(this.list + " li").each(function(item) {
  Event.stopObserving(item, 'click', this.showTagObserver);
}.bind(this));

One final note on removing event listeners. If you have an instance where you want to simply remove all observes in one big swoop, you can use unloadCache.

Event.unloadCache();

Summing Up

That pretty much sums up events in Prototype. If you find any errors, please let me know. The great thing about writing articles such as this is that I also learn so much in the process and develop a deeper understanding of what I'm writing about. For instance, I found out the removing event listeners bit while I was writing this article. If you've got anything you'd like to contribute, feel free to chime in. Until next time, Happy Prototyping!

Related Reading



TrampEagle 2006-02-11 14:04 发表评论
]]>
Maven 让事情变得简?/title><link>http://www.tkk7.com/TrampEagle/articles/30036.html</link><dc:creator>TrampEagle</dc:creator><author>TrampEagle</author><pubDate>Thu, 09 Feb 2006 06:52:00 GMT</pubDate><guid>http://www.tkk7.com/TrampEagle/articles/30036.html</guid><wfw:comment>http://www.tkk7.com/TrampEagle/comments/30036.html</wfw:comment><comments>http://www.tkk7.com/TrampEagle/articles/30036.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/TrampEagle/comments/commentRss/30036.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/TrampEagle/services/trackbacks/30036.html</trackback:ping><description><![CDATA[引自Q?a >http://www-128.ibm.com/developerworks/cn/java/j-maven/</a><br /><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr valign="top"><td width="100%"><h1><span style="COLOR: #999999">目理: </span>Maven 让事情变得简?/h1><p id="subtitle">l您的下一?Java 构徏d目理Ҏ?/p><img class="display-img" height="6" alt="" src="http://www.ibm.com/i/c.gif" width="1" /></td><td class="no-print" width="192"><img height="18" alt="developerWorks" src="http://www-128.ibm.com/developerworks/i/dw.gif" width="192" /></td></tr></tbody></table><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr valign="top"><td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td><td width="100%"><table class="no-print" cellspacing="0" cellpadding="0" width="160" align="right" border="0"><tbody><tr><td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td><td><table cellspacing="0" cellpadding="0" width="150" border="0"><tbody><tr><td class="v14-header-1-small">文档选项</td></tr></tbody></table><table class="v14-gray-table-border" cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="no-padding" width="150"><table cellspacing="0" cellpadding="0" width="143" border="0"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /><form name="email" action="https://www-130.ibm.com/developerworks/secure/email-it.jsp"><input type="hidden" value="管 Ant 对于构徏 Java E序而言是事实上的标准工P但这个工具在许多斚w都不胜Q目理d。相反,Ant 提供的东西,MavenQ出?Apache Jakarta 目的高U项目管理工P都能提供Q而且更多。Java 开发h?Charles Chan 介l?Maven 的特性,q@序渐q地指导您进行一ơ完整的 Maven 目讄? name="body" /><input type="hidden" value="目理: Maven 让事情变得简? name="subject" /><input type="hidden" value="cn" name="lang" /><script language="JavaScript" type="text/javascript"><!-- document.write('<tr valign="top"><td width="8"><img src="http://www.ibm.com/i/c.gif" width="8" height="1" alt=""/></td><td width="16"><img src="http://www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="此作为电子邮件发? /></td><td width="122"><p><a class="smallplainlink" href="javascript:document.email.submit();"><b>此作为电子邮件发?/b></a></p></td></tr>'); //--></script><tbody><tr valign="top"><td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td><td width="16"><img height="16" alt="此作为电子邮件发? src="http://www.ibm.com/i/v14/icons/em.gif" width="16" vspace="3" /></td><td width="122"><p><a class="smallplainlink" href="javascript:document.email.submit();"><b><font color="#5c81a7" size="2">此作为电子邮件发?/font></b></a></p></td></tr><noscript><tr valign="top"><td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td><td width="16"><img height="16" alt="" src="http://www.ibm.com/i/c.gif" width="16" /></td><td class="small" width="122"><p><span id="z3b3fnt" class="ast">未显C需?JavaScript 的文档选项</span></p></td></tr></noscript></tbody></form></table></td></tr></tbody></table></td></tr></tbody></table><br /><table cellspacing="0" cellpadding="0" width="150" border="0"><tbody><tr><td class="v14-header-1-small">Ҏ늚评h</td></tr></tbody></table><table class="v14-gray-table-border" cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="no-padding" width="150"><table cellspacing="0" cellpadding="0" width="143" border="0"><tbody><tr valign="top"><td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td><td><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/d_bold.gif" width="16" vspace="3" border="0" /></td><td width="125"><p><a class="smallplainlink" ><b><font color="#996699" size="2">帮助我们改进q些内容</font></b></a></p></td></tr></tbody></table></td></tr></tbody></table><br /></td></tr></tbody></table><p>U别: 初</p><p><a ><font color="#996699">Charles Chan</font></a>, 高软g开发h? Finetix LLC<br /></p><p>2003 q?7 ?30 ?/p><blockquote>管 Ant 对于构徏 Java E序而言是事实上的标准工P但这个工具在许多斚w都不胜Q目理d。相反,Ant 提供的东西,MavenQ出?Apache Jakarta 目的高U项目管理工P都能提供Q而且更多。Java 开发h?Charles Chan 介l?Maven 的特性,q@序渐q地指导您进行一ơ完整的 Maven 目讄?/blockquote><p>目前Q绝大多数开发h员都?Ant 当作 Java ~程目的标准构建工兗遗憄是,Ant 的项目管理工P作ؓ <code>make</code> 的替代工P不能满l大多数开发h员的需要。通过?Ant 构徏文gQ很隑֏现项目的相关性信息和其它元信息(如开发h员/拥有者、版本或站点主页Q?</p><p>Maven 除了以程序构力ؓ特色之外Q还提供 Ant 所~少的高U项目管理工兗由?Maven 的缺省构则有较高的可重用性,所以常常用两三?Maven 构徏脚本可以构建简单的目Q而?Ant 则需要十几行。事实上Q由?Maven 的面向项目的ҎQ许?Apache Jakarta 目现在使用 MavenQ而且公司目采用 Maven 的比例在持箋增长?/p><p><a name="1"><span id="99lxdt9" class="atitle"><font face="Arial" size="4">Maven vs Ant</font></span></a></p><p>那么QMaven ?Ant 有什么不同呢Q在回答q个问题以前Q我要强调一点:Maven ?Ant 针对构徏问题的两个不同方面。Ant ?Java 技术开发项目提供跨q_构徏d。Maven 本n描述目的高U方面,它从 Ant 借用了绝大多数构ZQ务。因此,׃ Maven ?Ant 代表两个差异很大的工P所以我只说明q两个工L{同lg之间的区别,如表 1 所C?/p><p><a name=" "><span id="39dxjzf" class="smalltitle"><strong><font face="Arial">?1. Maven vs Ant</font></strong></span></a></p><p></p><table cellspacing="0" cellpadding="3" width="600" border="1"><tbody><tr><td><strong><font face="Arial"></font></strong></td><td><strong>Maven</strong></td><td><b>Ant</b></td></tr><tr><td>标准构徏文g</td><td>project.xml ?maven.xml</td><td>build.xml</td></tr><tr><td>Ҏ处理顺?/td><td><ol><li>${maven.home}/bin/driver.properties </li><li>${project.home}/project.properties </li><li>${project.home}/build.properties </li><li>${user.home}/build.properties </li><li>通过 -D 命o行选项定义的系l特?</li></ol><b>最后一?/b>定义起决定作用?</td><td><ol><li>通过 -D 命o行选项定义的系l特? </li><li>?<code><property></code> d装入的特?</li></ol><b>W一?/b>定义最先被处理?</td></tr><tr><td>构徏规则</td><td>构徏规则更ؓ动态(cM于编E语aQ;它们是基?Jelly 的可执行 XML?/td><td>构徏规则或多或少是静态的Q除非?<code><script></code> d。(请参?<a ><font color="#996699">参考资?/font></a>以获得相xE。) </td></tr><tr><td>扩展语言</td><td>插g是用 JellyQXMLQ编写的?/td><td>插g是用 Java 语言~写的?/td></tr><tr><td>构徏规则可扩展?/td><td>通过定义 <code><preGoal></code> ?<code><postGoal></code> 使构?goal 可扩展?</td><td>构徏规则不易扩展Q可通过使用 <code><script></code> d模拟 <code><preGoal></code> ?<code><postGoal></code> 所L作用?</td></tr></tbody></table><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></td><td valign="top" align="right"><a class="fbox" ><b><font color="#996699">回页?/font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="2"><span id="b39r9f9" class="atitle"><font face="Arial" size="4">Maven 的主要组?/font></span></a></p><p>既然您了解了 Maven ?Ant 之间的区别,让我们来研究 Maven 的主要组Ӟ如图 1 所C?/p><br /><a name="N100FE"><b>?1. Maven 的主要组?</b></a><br /><img height="183" alt="Maven 的主要组? src="http://www-128.ibm.com/developerworks/cn/java/j-maven/images/overview.gif" width="458" /><br /><p><a name="N1010B"><span id="3fln3lz" class="smalltitle"><strong><font face="Arial">目对象模型</font></strong></span></a></p><p>目对象模型QProject Object ModelQPOMQ描q项目的各个斚w。尽对?POM 的物理表C没有内在的限制Q但 Maven 开发h员通常使用一?XML 目文gQproject.xmlQ。该 XML 文g格式׃?Maven 安装目录中的 XML 模式Qmaven-project.xsdQ定义?/p><p>通常Qproject.xml 文g׃个主要部分组成:</p><ul><li>目理部分包括目的组l、开发h员名单、源代码位置和错误跟t系l?URL {信息? </li><li>目相关性部分包括关于项目相x的信息。当?Maven 实现Q?.0 beta 试?8Q仅支持 JAR 文g相关性? </li><li>目构徏和报告部分包含项目构Z息(如源代码目录、单元测试用例目录)和要在构Z生成的报告?</li></ul><p>清单 1 昄了带注释的样?project.xml 文g。因?project.xml 文g中的许多元素都是可选的Q所以,随着您对 Maven 理解的加深,可以逐步使用不同?Maven Ҏ?<i>注:在以下代码中Q可选的元素都以“可选的QOPTIONALQ”标明?/i></p><p>L档包含项目的唯一标识和组标识。事实证明,当项目包括多个子目Ӟl标识非常有用。所有的子项目应׃n同一l标识,但每个子目应有不同?<code><id></code> ?</p><br /><a name="N10130"><b>清单 1. ?project.xml 框架</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"><?xml version="1.0" encoding="ISO-8859-1"?> <!-- A project file's root element --> <project> <!-- The POM version. This tag is currently unused. --> <pomVersion>3</pomVersion> <!-- A project group id. If present, the id serves as the project's directory name in the repository --> <groupId>crayola-group</groupId> <!-- A unique project identifier. The project identifier and its version number often generate file/directory names during the build. For example, a project JAR file follows the <id>-<version> naming convention. --> <id>crayola</id> <!-- A short name for the project --> <name>Crayola Professional</name> <!-- The project version number. Maven does not enforce a particular version numbering scheme. --> <currentVersion>0.0.1</currentVersion> ... <!-- ---------------------------------------------------------------- --> <!-- Project management section --> <!-- ---------------------------------------------------------------- --> ... <!-- ---------------------------------------------------------------- --> <!-- Project dependency section --> <!-- ---------------------------------------------------------------- --> ... <!-- ---------------------------------------------------------------- --> <!-- Project build and reports section --> <!-- ---------------------------------------------------------------- --> ... </project> </font></code></pre></td></tr></tbody></table><br /><p>目理部分Q如清单 2 所C)主要包括可选项。在此部分中指定开发h员名单(带有正确的标识)Q当您希望获得更Ҏ志(Change LogQ报告和开发活动(Development ActivityQ报告时其要这么做?/p><br /><a name="N1013D"><b>清单 2. 目理部分</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"> ... <!-- ---------------------------------------------------------------- --> <!-- Project management section --> <!-- ---------------------------------------------------------------- --> <!-- Details of the organization holding the project. Only the name is required. --> <organization> <name>Markers Inc.</name> <url>http://w3.markers.com/</url> <logo>http://w3.markers.com/logo/company-logo.gif</logo> </organization> <!-- (OPTIONAL) Year of inception --> <inceptionYear>2003</inceptionYear> <!-- (OPTIONAL) Project main package --> <package>com.markers.crayola.*</package> <!-- (OPTIONAL) Project logo picture (URL) --> <logo>http://w3.markers.com/logo/crayola.gif</logo> <!-- (OPTIONAL) GUMP repository ID. Useful only if you use GUMP. --> <gumpRepositoryId>crayola</gumpRepositoryId> <!-- (OPTIONAL) Project description --> <description>...</description> <!-- (OPTIONAL) Short project description --> <shortDescription>...</shortDescription> <!-- (OPTIONAL) Project site URL --> <url>http://w3.markers.com/crayola</url> <!-- (OPTIONAL) Issue-tracking system URL --> <issueTrackingUrl>http://w3.markers.com/jira/crayola</issueTrackingUrl> <!-- (OPTIONAL) Project site address. --> <siteAddress>w3.markers.com</siteAddress> <!-- (OPTIONAL) Project-site deploy directory (physical location) --> <siteDirectory>/www/crayola/site/</siteDirectory> <!-- (OPTIONAL) Project distribution directory (physical location) --> <distributionDirectory>/www/crayola/builds/</distributionDirectory> <!-- (OPTIONAL) Project source-repository information --> <repository> <connection> scm:cvs:pserver:anoncvs@cvs.markers.com:/home/cvspublic:crayola </connection> <url>http://cvs.markers.com/viewcvs/crayola/</url> </repository> <!-- (OPTIONAL) Mailing list information --> <mailingLists> <mailingList> <name>Dev List</name> <subscribe>dev-subscribe@crayola.markers.com</subscribe> <unsubscribe>dev-unsubscribe@crayola.markers.com</unsubscribe> </mailingList> ... </mailingLists> <!-- Developers involved in this project --> <developers> <developer> <name>John Smith</name> <id>jsmith</id> <email>jsmith@markers.com</email> </developer> ... </developers> </font></code></pre></td></tr></tbody></table><br /><p>清?3 中的信息与一个中央构件资源库一起用,消除几个常见的构徏问题Q包括错误配|的 <code>CLASSPATH</code> 或相x?版本不匹配)?</p><br /><a name="N1014E"><b>清单 3. 目相关性部?/b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"> <!-- ---------------------------------------------------------------- --> <!-- Project dependency section --> <!-- ---------------------------------------------------------------- --> <dependencies> <!-- This project depends on the JAR file "commons-beanutils-1.5.jar" in the Maven repository's commons-beanutils/jars subdirectory (more about repository later). --> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.5</version> </dependency> <!-- This project depends on the JAR file "commons-lib-2.1.jar" in the Maven repository's markers/jars subdirectory. --> <dependency> <groupId>markers</groupId> <artifactId>commons-lib</artifactId> <version>2.1</version> </dependency> </dependencies> </font></code></pre></td></tr></tbody></table><br /><p>目构徏和报告部分(如清?4 所C)包含用于配置某些 Maven 插g的重要构建和报告信息。例如,可以配置 Maven 在站Ҏ档生成时包含q是排除某些报告?/p><br /><a name="N1015B"><b>清单 4. 目构徏部分</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"> ... <!-- ---------------------------------------------------------------- --> <!-- Project build and reports section --> <!-- ---------------------------------------------------------------- --> <build> <!-- (OPTIONAL) Build notification email address. --> <nagEmailAddress>jsmith@markers.com</nagEmailAddress> <!-- (OPTIONAL) Defines where the Java source resides. --> <sourceDirectory>src/java</sourceDirectory> <!-- (OPTIONAL) Defines where the Java source for unit test-cases resides. --> <unitTestSourceDirectory>test/java</unitTestSourceDirectory> <!-- (OPTIONAL) Unit test-case file pattern. --> <unitTest> <includes> <include>**/*Test.java</include> </includes> </unitTest> <!-- (OPTIONAL) Resources packaged inside the JAR file. --> <resources/> <!-- (OPTIONAL) The reports tag lets you select which reports you want generated for your site. In this case, only the checkstyle report will generate. --> </build> <reports> <report> maven-checkstyle-plugin </report> </reports> </font></code></pre></td></tr></tbody></table><br /><p>目依靠库来实现其功能。例如,您的目可能依靠 log4j q行日志记录Q依?Xalan q行 XSLT 转换。对?J2EE 目QWeb lg可能依靠 EJB lg来执行业务操作。Maven 可以让您用它?POM 来表CZ同的相关性。您可以用表 2 所C的标记?project.xml 文g中描q每一个相x?/p><p><a name=" "><span id="xxtnpp3" class="smalltitle"><strong><font face="Arial">?2. 目相关性部?/font></strong></span></a></p><p></p><table cellspacing="0" cellpadding="3" width="100%" border="1"><tbody><tr><td><strong>groupId</strong></td><td>告诉 Maven 资源库内哪个子目录中包含相关性文件?/td></tr><tr><td><b>artifactId</b></td><td>告诉 Maven 该构件的唯一标识?/td></tr><tr><td><b>version</b></td><td>表示相关性的版本受?/td></tr><tr><td><b>jar</b></td><td>Q可选的Q表C相x的 JAR 文g。在l大多数情况下,可以从相x的 <code><artifactId></code> ?<code><version></code> 构?JAR 文g的名U?</td></tr><tr><td><b>type</b></td><td>Q可选的Q相x的cdQ如 jar 和分发版{。缺省值是 jar?/td></tr><tr><td><b>url</b></td><td>Q可选的Q相x项目的 URLQ在相关性是在因特网上找到的W三方库旉常有用?/td></tr></tbody></table><p><a name="N101C8"><span id="9j999l9" class="smalltitle"><strong><font face="Arial">资源?/font></strong></span></a></p><p>资源库是另一个主要的 Maven lg。在有多个项目的Z Java 的站点中Q由W三方库l成的中央资源库常常保目之间的一致性。Maven 使资源库的结构符合标准,q且支持ȝ在因特网或内部网上的q程资源库。清?5 昄了资源库的常规结构?/p><br /><a name="N101D1"><b>清单 5. 资源?/b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">repository |-- ant <-- project group ID --> | `-- jars <-- artifact type, followed by 's', | <-- e.g. jars, wars, ears --> | `-- ant-1.5.1.jar <-- actual artifact --> ... </font></code></pre></td></tr></tbody></table><br /><p>要创E资源库Q只需这个资源库的目录部|在|站中。Maven 使用q程资源库以便于集中l护Q您会最大程度地实现目之间资源的共享。ؓ避免每次构徏旉要下载文ӞMaven 在首ơ下载必需的相x资源时p动地其高速缓存在本地资源库中。Maven 表 3 中所C的Ҏ用于远E资源库和本地资源库?/p><p><a name=" "><span id="tnhtndt" class="smalltitle"><strong><font face="Arial">?3. 用于q程资源库和本地资源库的Ҏ?/font></strong></span></a></p><p></p><table cellspacing="0" cellpadding="3" width="100%" border="1"><tbody><tr><td><code>maven.repo.remote</code></td><td>用以逗号分隔?URL 列表指定q程资源库;~省情况下?http://www.ibiblio.org/maven?/td></tr><tr><td><code>maven.proxy.host</code> ?<code>maven.proxy.port</code> ?<code>maven.proxy.username</code> ?<code>maven.proxy.password</code></td><td>如果位于防火墙后面ƈ且需要代理认证才能访问因特网Q这些设|将z上用场?/td></tr><tr><td><code>maven.repo.local</code></td><td>指定已下载的相关资源的高速缓存位|,~省gؓ <code>${MAVEN_HOME}/repository</code> 。在 UNIX 环境中,Z与多个团队共享资源库目录Q可以ؓ开发h员创Z个特D的l,然后l予q个l对资源库目录的读/写访问权?</td></tr></tbody></table><table cellspacing="0" cellpadding="0" width="40%" align="right" border="0"><tbody><tr><td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td><td><table cellspacing="0" cellpadding="5" width="100%" border="1"><tbody><tr><td bgcolor="#eeeeee"><a name="N10227"><b>Maven 中的 Ant d</b></a><br /><p>Maven 中的 goal 可在其定义中包含M有效?Ant dQ这一Ҏ助于您快速掌?Maven 以及保护您的 Ant 投入?/p></td></tr></tbody></table></td></tr></tbody></table><p><a name="N10231"><span id="99zlp99" class="smalltitle"><strong><font face="Arial">goal</font></strong></span></a></p><p>Maven 中的 goal cM Ant 中的 <code>target</code> 。两者都包含实现 goalQ或 targetQ时会执行的d。要在命令行中实现特定的 goalQ可输入 <code>maven <goal></code> ?</p><p>要列出所有已定义?goalQ可使用 <code>maven -g</code> 。表 4 列出了常用的 goal?</p><p><a name=" "><span id="nvzjnl9" class="smalltitle"><strong><font face="Arial">?4. 常用?goal</font></strong></span></a></p><p></p><table cellspacing="0" cellpadding="3" width="100%" border="1"><tbody><tr><td><code>java:compile</code></td><td>~译所?Java 源代码?/td></tr><tr><td><code>jar</code></td><td>创徏已编译的源代码的 JAR 文g?/td></tr><tr><td><code>jar:install</code></td><td>已创徏?JAR 文g发布到本地资源库Q得其它项目可讉K?JAR 文g?/td></tr><tr><td><code>site</code></td><td>创徏目站点文档。缺省站Ҏ档包含关于项目的有用信息Q如包/cȝx、编码风g致性、源代码交叉引用、单元测试结果或 Javadoc。要生成的报告列表是可定制的?/td></tr><tr><td><code>site:deploy</code></td><td>部v生成的站Ҏ档?/td></tr></tbody></table><p>Maven ?goal 是可扩展和可重用的。知道了q一点后Q在~写自己?goal 之前Q可先在 Maven 站点上或 <code>${MAVEN_HOME}/plugins</code> 中查?Maven 插g列表。另一个关于免?Maven 插g的较佌源是 SourceForge 上的 Maven 插g目。(以上各项的链接可?<a ><font color="#996699">参考资?/font></a>中获得)?</p><p>如果仍不能找到符合您要求?goalQMaven l您两种选择Q?/p><ul><li>~写 <code><preGoal></code> ?<code><postGoal></code> 来扩展标?goal </li><li>~写自己?goal </li></ul><p>无论选择哪种Q都要在目目录中创建名?maven.xml 的特D文件。清?6 昄了框?maven.xml?/p><br /><a name="N102BC"><b>清单 6. 框架 maven.xml</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"> <?xml version="1.0" encoding="ISO-8859-1"?> <project xmlns:j="jelly:core"> ... <goal name=...> ... build rules, e.g. <mkdir dir="${test.result.dir}"/> <echo>Executing JUnit tests</echo> ... </goal> ... <preGoal name=...> ... </preGoal> <postGoal name=...> ... </postGoal> </project> </font></code></pre></td></tr></tbody></table><br /><p>熟悉 Ant 的开发h员会发现 Maven ?goalQ同栯?<code>preGoal</code> ?<code>postGoal</code> Q可在其定义中包含Q何有效的 Ant dQ这有助于快速学?Maven q保护在 Ant 上的投入。ؓ了给 Ant dd动态性,Maven 也?Jelly 脚本~制语言。?<a ><font color="#5c81a7">基础 Jelly ~程</font></a>”用一个样?maven.xml 文g介绍 Jelly 脚本~制语言?</p><p><b>~写 <preGoal> ?<postGoal></b><br />Ant ?<code><target></code> ?<code>makefile</code> 规则的相g处在于:定义了规则以后,前提条g和后|条件是固定的。这使得在多个项目间重用构徏规则变得更加困难。例如,某个目中的 <code>compile</code> target 可能依靠 XDoclet 生成源文Ӟ而另一?<code>compile</code> target 可能不包括Q何先x件。ؓ了克服这U限ӞMaven 提供了两个特D标讎ͼ <code><preGoal></code> ?<code><postGoal></code> 。从标记的名U可以看出: <code>preGoal</code> 定义在指定的 goal 之前执行的构则。另一斚wQ?<code>postGoal</code> 定义实现指定 goal 之后要执行的构徏规则。例如,清单 7 中的 <code>preGoal</code> 指示 Maven 在编译源代码之前?XDoclet 生成源文件?</p><br /><a name="N10301"><b>清单 7. h preGoal 部分</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"> <preGoal name="java:compile"> <attainGoal name="xdoclet:ejbdoclet"/> </preGoal> </font></code></pre></td></tr></tbody></table><br /><p>Maven q提供与 Ant ?<code><antcall></code> 标记怼?<code><attainGoal></code> 标记Q以便在有必要直接实现 goal 的情况(如上例)下用?</p><p><b>~写自己?goal</b><br />如果 goal 是特定于目的,则可?maven.xml 文g中定义自q goal。这些自定义?goal 会覆盖其它同名的 goal。如果项目包括子目Q子目也承这?goal?</p><p><b>~写插g</b><br />Z在项目间׃n goalQ可?Maven 安装插g目录Q?<code>${MAVEN_HOME}/plugins</code> Q中其打包为插件。典型的 Maven 插g包含 project.xml ?plugin.jelly 文g。project.xml 文g描述插g?POMQplugin.jelly cM maven.xml 且包含该插g所展示?goal。插件可以有自己的资源和相关性信息。预先定义的变量 <code>${plugin.dir}</code> 让用户引用插件目录中的资源。例如,在清?8 中所C的插gl构中, <code>${plugin.dir}/dtd/web-app_2_3.dtd</code> 可访?<code>plugin.jelly</code> 中的 <code>web-app_2_3.dtd</code> ?</p><br /><a name="N1033A"><b>清单 8. h插gl构</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"> ejbjar-plugin-1.0 |-- dtd | |-- application_1_3.dtd | |-- ejb-jar_2_0.dtd | |-- web-app_2_3.dtd |-- plugin.jelly `-- project.xml </font></code></pre></td></tr></tbody></table><br /><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><font face="Lucida Console"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /></font></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><font face="Lucida Console"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></font></td><td valign="top" align="right"><a class="fbox" ><b><font color="#996699">回页?/font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="3"><span id="tl9xpn9" class="atitle"><font face="Arial" size="4">安装 Maven</font></span></a></p><p>最q发行的 Maven 1.0-beta-8 基本上是 1.0 的功能完善版。因?Maven 开发社区每天都在修正错误,如果您遇CQ何无法正常工作的问题Q则立即?CVSQConcurrent Version SystemQƈ发版本控制系l)获得最?Maven 版本Q然后自行构建(请参?<a ><font color="#996699">参考资?/font></a>以获得指CZ息)。下载了最新的 Maven 源代码之后,可通过调用以下命o来构?MavenQ?</p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"> ant -f build-bootstrap.xml (set MAVEN_HOME to where you want Maven to reside and use Ant 1.5.1 to perform the build) </font></code></pre></td></tr></tbody></table><br /><p>如果在防火墙之后操作Q请正确讄以下Ҏ: <code>maven.proxy.host</code> ?<code>maven.proxy.port</code> ?<code>maven.proxy.username</code> ?<code>maven.proxy.password</code> 。缺省情况下QMaven 资源库驻留在 <code>${MAVEN_HOME}/repository</code> 中;通过?<code>maven.repo.local</code> Ҏ设|ؓC|,可以更改 Maven 资源库的位置?</p><table cellspacing="0" cellpadding="0" width="40%" align="right" border="0"><tbody><tr><td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td><td><table cellspacing="0" cellpadding="5" width="100%" border="1"><tbody><tr><td bgcolor="#eeeeee"><a name="N10372"><b>h目文g</b></a><br /><p>请参阅在q个h J2EE 目中用的 <a ><font color="#5c81a7">Maven 目文g</font></a>?</p></td></tr></tbody></table></td></tr></tbody></table><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></td><td valign="top" align="right"><a class="fbox" ><b><font color="#996699">回页?/font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="4"><span id="x3nxthp" class="atitle"><font face="Arial" size="4">h J2EE 目</font></span></a></p><p>掌握了到目前为止所学的知识后,可以着手?Maven 了。本节描q如何用 Maven 讄一个样?J2EE 目?/p><p><a name="N10389"><span id="9h99jh9" class="smalltitle"><strong><font face="Arial">目目录布局</font></strong></span></a></p><p>在进行详l介l之前,我先说明一下项目的目录布局。尽不作要求,但事实证明一致的跨项目目录布局非常有用Q因为熟悉了一个项目的开发h员可以轻村֜览其它目。更重要的是Q一致的目录布局可让您编写通用的构则?/p><p>Maven 的目录布局指南Q请参阅 <a ><font color="#996699">参考资?/font></a>Q适用于绝大多数项目。作为演C,我用略微不同的布局Q如清单 9 所C?</p><br /><a name="N10399"><b>清单 9. h目目录布局</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"> project | |-- LICENSE.txt |-- project.properties |-- maven.xml |-- project.xml |-- src | `-- java | `-- com/.... | `-- conf | `-- Configuration files for staging environments. |-- test | `-- java | `-- com/.... | `-- conf | `-- Configuration files for unit testing environments. `-- xdocs `-- index.xml </font></code></pre></td></tr></tbody></table><br /><p>一?J2EE 目通常生成 WAR 文g、EJB JAR 文g?EAR 文g。因为每U文仉包括自己的相x信息和源文Ӟ所以应其作ؓ单独目来构建。通常Q通过子目存储Z目的子目录Q来构造这一目Q子目关系。我们的布局如清?10 所C?/p><br /><a name="N103A6"><b>清单 10. Maven ?J2EE 目的高U目录布局</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console">j2ee-project | |-- project.xml - Produces the EAR file | |-- util-subproject | | | `-- project.xml - Produces the Utility JAR file | |-- ejb-subproject | | | `-- project.xml - Produces the EJB JAR file | `-- web-subproject | `-- project.xml - Produces the WAR file </font></code></pre></td></tr></tbody></table><br /><p><a name="N103B0"><span id="hfztx39" class="smalltitle"><strong><font face="Arial">目l承</font></strong></span></a></p><p>目l承?POM 以类g对象l承的方式从?POM l承 ?׃q些目之间的细微差别(主要是相x的差别Q,q一Ҏ在此尤为重要。项目管理部分可在主 project.xml 中集中维护。要使用目l承Q可使用 project.xml 中的 <code><extend></code> 标记Q请参阅?<a ><font color="#5c81a7">h目文g</font></a>”中的清?2Q?</p><p><a name="N103C1"><span id="3pnh999" class="smalltitle"><strong><font face="Arial">h目?goal</font></strong></span></a></p><p>既然已经定义?POMQ就可以~写它们?goal。因?goal 使用 POM 中定义的Ҏ,所以在l箋之前应该首先理解?<a ><font color="#5c81a7">h目文g</font></a>”中?project.xml 文g?</p><p><a name="N103CE"><span id="rp39r9d" class="smalltitle"><strong><font face="Arial">Utility 子项?/font></strong></span></a></p><p>׃ Utility 子项目生成一个包含源目录中类?JAR 文g ?q省的 <code>jar:jar</code> goal 卛_满要求Q因此这里不需要定制的 goal?</p><p>因ؓ Web 子项目和 EJB 子项目都依靠 Utility 子项目,所以,在构?Web 子项目和 EJB 子项目之前,应该调用 <code>jar:install</code> goal 以将 Utility 子项?JAR 文g部v到本地资源库。这PWAR 子项目和 EJB 子项目就可以正确地解析相x?</p><p><a name="N103E2"><span id="9ndhbrz" class="smalltitle"><strong><font face="Arial">Web 子项?/font></strong></span></a></p><p>Web 子项目生成一?WAR 文gQ该文g包含源目录的cR?<code>jsp</code> 目录中的 JSP 文g?<code>conf</code> 目录中的 web.xml 文g。缺?<code>war:war</code> goal 有更单的关于目目录布局的视图。要重用?goalQ可如下定制其行为: </p><ol><li>在项目的 project.properties 文g中,特?<code>maven.war.src</code> ?<code>maven.war.webxml</code> 分别讄?<code>${maven.build.dir}/webapp</code> ?<code>${maven.src.dir}/conf/web.xml</code> 。这告诉 <code>war:war</code> 在哪里查?Web 来源QJSP 面、HTML 静态页面和囑փ{)?web.xml 文g?<br /></li><li>定义一个将所?JSP 文g复制?<code>${maven.build.dir}/webapp</code> 目录中的 <code>preGoal</code> 。以?maven.xml 可实现这一效果Q? <p></p><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"><?xml version="1.0" encoding="ISO-8859-1"?> <project> <preGoal name="war:init"> <copy todir="${maven.build.dir}/webapp"> <fileset dir="${maven.src.dir}/jsp" include="*.jsp"/> </copy> </preGoal> </project> </font></code></pre></td></tr></tbody></table><br /></li></ol><p>当调?<code>war:war</code> goal Ӟh?Utility JAR 文g?commons-beanutils JAR 文g都被打包?WAR 文g。通过查看 project.xml 文g的相x部分中?<code>war.bundle.jar</code> Ҏ,Maven 知道要在 WAR 文g中包括哪个文件?</p><p><a name="N10430"><span id="3xrd9lb" class="smalltitle"><strong><font face="Arial">EJB 子项?/font></strong></span></a></p><p>l?EJB JAR 文g打包和给 JAR 文g打包怼。如果项目设|与~省 <code>ejb</code> goal 不匹配,可应用以上“Web 子项目”一节中所描述的技术。在q个特定例子中,?ejb-jar.xml ?<code>conf</code> 目录复制?<code>${maven.build.dir}/ejb/META-INF</code> 目录Qƈ?<code>maven.ejb.src</code> Ҏ设|ؓ <code>${maven.build.dir}/ejb</code> ?</p><p>要将相关?JAR 文gd?EJB JAR 的清单类路径Qmanifest classpathQ中Q可在相x部分中使用 <code>ejb.manifest.classpath</code> Ҏ?</p><p><a name="N10454"><span id="bz93rhx" class="smalltitle"><strong><font face="Arial">主(EARQ项?/font></strong></span></a></p><p>在成功编译ƈ部v了子目Q?<code>jar:install</code> ?<code>war:install</code> ?<code>ejb:install</code> goalQ之后,卛_创徏最l的 EAR 文g。相x特?<code>ear.bundle.jar</code> ?<code>ear.bundle.ejb</code> ?<code>ear.bundle.war</code> 告诉 <code>ear</code> 插g要在 EAR 文g中包括哪些文件。(对于 Maven 1.0-beta-8QWAR 文g不是受支持的相关性类型,因此 EAR 插g不能正确地给 WAR 文g打包。解军_法:使用 <code>postGoal</code> 手工更新 EAR 文g。) </p><p><a name="N1047D"><span id="vl9jflb" class="smalltitle"><strong><font face="Arial">reactorQ自动构建子目</font></strong></span></a></p><p>构徏 J2EE 目需要大量的工作。事实证明,每次目更改旉复同Lq程耗费旉而且Ҏ出错。ؓ帮助解决q些问题QMaven ?reactor 功能部g以正的序自动构徏子项目,q样p省了旉且减了错误?/p><p>清单 11 ?maven.xml 演示了定?reactor 的方法?/p><br /><a name="N10489"><b>清单 11. h reactor 定义</b></a><br /><table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1"><tbody><tr><td><pre><code class="section"><font face="Lucida Console"><?xml version="1.0" encoding="ISO-8859-1"?> <project default="all" xmlns:m="jelly:maven"> <goal name="all"> <m:reactor basedir="${basedir}" includes="*/project.xml" goals="install" banner="Building" ignoreFailures="false"/> </goal> </project> </font></code></pre></td></tr></tbody></table><br /><p>?reactor 首先?<code>basedir</code> 目录下搜?project.xml 文gQ然后调?<code>install</code> goal。执行的序取决于每个项目中的相x部分。此外,通常可以在主目?maven.xml 文g中定?reactor。因?goal 在子目中承,所以选择 goal 的名U时要当心?</p><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></td><td valign="top" align="right"><a class="fbox" ><b><font color="#996699">回页?/font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="5"><span id="31r9vdb" class="atitle"><font face="Arial" size="4">参与其中</font></span></a></p><p>管 Maven 是功能丰富的产品Q但它仍处于 beta 试版阶Dc因此错误可能在M地方H然出现。别慌。要扑ֈ解决错误的答案,最好的办法是搜?Maven 的邮件列表归档(请参?<a ><font color="#996699">参考资?/font></a>Q以了解相关的通告。如果没有Q何发玎ͼ试着问题公布到邮g列表Q以便得到别人的。邮件列表上列出的h一般都乐于l予帮助?</p><p>要正式地报告错误Q请讉K Maven 目的问题跟t系l(请参?<a ><font color="#996699">参考资?/font></a>Q?</p><p>一旦熟悉了 MavenQ您可能会在插g的实C扑ֈl大多数{案。当您达C家水q_ƈ且相?Maven 大有前途的时候,请向C֌提供补丁Q帮?Maven 成长?/p><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></td><td valign="top" align="right"><a class="fbox" ><b><font color="#996699">回页?/font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="6"><span id="39z9nd9" class="atitle"><font face="Arial" size="4">l束?/font></span></a></p><p>随着如今的项目变得越来越复杂Q我们需要能帮助我们表示q管理这些复杂性的工具。Maven 项目对象模型与功能强大?XML 脚本~制语言相结合,为我们提供了q样的工兗在本文中,您已l了解如何定?POM 以及如何使用 Maven ?<code>goal</code> 机制构徏目。我们还研究了?Jelly 定制构徏行ؓ的不同方法。最后,利用一个样?J2EE 目Q我们将概念在实际中加以应用。希望您下蝲 Maven 以推动其发展?</p><p><i>作者感?Jason van Zyl Ҏ文的评审?/i></p><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></td><td valign="top" align="right"><a class="fbox" ><b><font color="#996699">回页?/font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="resources"><span id="x3vpj3d" class="atitle"><font face="Arial" size="4">参考资?</font></span></a></p><ul><li>您可以参阅本文在 developerWorks 全球站点上的 <a ><font color="#5c81a7">英文原文</font></a>. <br /><br /></li><li>有关 Maven 及其各种插g的更多信息,误?<a ><font color="#5c81a7">Maven</font></a>|站。您在那里发现有用的参考资料,包括Q? <ul><li>推荐?<a ><font color="#5c81a7">目录布局</font></a></li><li><a ><font color="#5c81a7">内置插g文档</font></a></li><li><a ><font color="#5c81a7">邮g列表</font></a></li><li>使用 Maven ?<a ><font color="#5c81a7">目列表</font></a></li><li>Maven <a ><font color="#5c81a7">CVS 资源?/font></a></li><li><a ><font color="#5c81a7">Maven User Guide</font></a>Q针?1.0-beta-8 更新 </li></ul><br /><br /></li><li>Sourceforge.net ?<a ><font color="#5c81a7">Maven 插g</font></a>目提供免费 Maven 插g?<br /><br /><br /></li><li>Maven ?<a ><font color="#5c81a7">问题跟踪pȝ</font></a>可用于报告和查询错误?<br /><br /><br /></li><li><a ><font color="#5c81a7">Jelly |站</font></a>?Jelly 标记的出色引用是该站点的一大亮炏V?<br /><br /><br /></li><li>Maven ?<a ><font color="#5c81a7">API 文档</font></a>在您使用 Jelly ~写构徏规则时会非常有用?<br /><br /><br /></li><li><a ><font color="#5c81a7">Ant |站</font></a>提供?Ant d的出色引用。在 Maven 中可使用l大多数 Ant d?<br /><br /><br /></li><li>教程?<a ><font color="#5c81a7">Using JavaScript with Ant</font></a>”向您演C如何用 JavaScript ~写动?Ant d?<br /><br /><br /></li><li><a ><font color="#5c81a7">Krysalis Centipede</font></a>是另一个基?Ant 的构建系l?<br /><br /><br /></li><li>在?<a ><font color="#5c81a7">Extending Ant to support interactive builds</font></a>”( <i>developerWorks</i>Q?001 q?11 月)中,Anthony Young-Garner 向您演示如何在构Z加入交互式支持,以便为最l用h供更畅、更灉|的体验?<br /><br /><br /></li><li>Malcolm Davis 撰写的?<a ><font color="#5c81a7">利用 Ant ?JUnit q行增量开?/font></a>”( <i>developerWorks</i>Q?000 q?11 月)用单元测试改q代码?<br /><br /><br /></li><li><a ><font color="#5c81a7">GUMP</font></a>是连l集成相互从属的目的工兗?<br /><br /><br /></li><li>?<a ><font color="#5c81a7">Automated builds with VisualAge for Java and Ant</font></a>”( <a ><font color="#5c81a7"><i>WebSphere 开发者园?/i></font></a>Q?001 q?1 月)介绍如何为项目创动化构徏?<br /><br /><br /></li><li>您将?<a ><font color="#5c81a7"><i>developerWorks</i>Java 技术专?</font></a>扑ֈ涉及 Java ~程各个斚w的数癄文章?<br /><br /></li></ul><br /><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /></td></tr></tbody></table><table class="no-print" cellspacing="0" cellpadding="0" align="right"><tbody><tr align="right"><td><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /></td><td valign="top" align="right"><a class="fbox" ><b><font color="#996699">回页?/font></b></a></td></tr></tbody></table></td></tr></tbody></table><br /><br /><p><a name="author"><span id="jp9z99n" class="atitle"><font face="Arial" size="4">关于作?/font></span></a></p><table cellspacing="0" cellpadding="0" width="100%" border="0"><tbody><tr><td colspan="2"><font face="Arial" size="4"><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /></font></td></tr><tr valign="top" align="left"><td><p><font face="Arial" size="4"></font></p></td><td><p>Charles Chan ?Finetix LLC 的一名顾问。Charles 的兴包括分布式pȝ、高性能计算、国际化和Y件设计模式。在业余旉Q他为开放源码社区撰Eѝ可以通过 <a href="mailto:charlesc@ibiblio.org"><font color="#5c81a7">charlesc@ibiblio.org</font></a> ?Charles 联系?</p></td></tr></tbody></table><img src ="http://www.tkk7.com/TrampEagle/aggbug/30036.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/TrampEagle/" target="_blank">TrampEagle</a> 2006-02-09 14:52 <a href="http://www.tkk7.com/TrampEagle/articles/30036.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://jl910.com" target="_blank">߿Ƭ˳Ƶ </a>| <a href="http://gujingyuye.com" target="_blank">4ѵַ</a>| <a href="http://s88s88.com" target="_blank">ܲƵ</a>| <a href="http://udlmw.com" target="_blank">Ƶѹۿ</a>| <a href="http://kppp4.com" target="_blank">޹þþۺ</a>| <a href="http://shaiyahx.com" target="_blank">777777</a>| <a href="http://91xx8.com" target="_blank">18ڵվ</a>| <a href="http://626632.com" target="_blank">Ƶ97</a>| <a href="http://22youjizz.com" target="_blank">޾Ʒһۺ</a>| <a href="http://hzkjjy.com" target="_blank">2020þþƷۺһ</a>| <a href="http://2886868.com" target="_blank">91˾Ʒϵȫ</a>| <a href="http://66h99.com" target="_blank">ɫվWWWþþž</a>| <a href="http://snbbearing.com" target="_blank">ᰡͣѿ</a>| <a href="http://zaideqin.com" target="_blank">ԲaëƬ</a>| <a href="http://bdykdq.com" target="_blank">ھƷ鶹վ91鶹</a>| <a href="http://skcncar.com" target="_blank">ůůձ</a>| <a href="http://dt677.com" target="_blank">ֻˬִƵ</a>| <a href="http://zhuanjiao521.com" target="_blank">gayˬˬƵ</a>| <a href="http://qzapp88.com" target="_blank">޾ƷƷ</a>| <a href="http://anhuish.com" target="_blank">߹ۿAVպA</a>| <a href="http://9xcb.com" target="_blank">AVۺɫ͵</a>| <a href="http://138site.com" target="_blank">ۺ߳һ</a>| <a href="http://222dv.com" target="_blank">޹ۺרߵӰ</a>| <a href="http://yuase.com" target="_blank">AVҹƬ</a>| <a href="http://52ku6.com" target="_blank">ͬ˧GAYƬ߹ۿ</a>| <a href="http://aidannis.com" target="_blank">Ʒһ߹ۿ </a>| <a href="http://9v9av.com" target="_blank">AVרߵӰ</a>| <a href="http://pohezi.com" target="_blank">޹Ʒ߹ۿ</a>| <a href="http://www-bajie.com" target="_blank">ŷղwww</a>| <a href="http://8888kkk.com" target="_blank">Ʒ޳AA߹ۿ</a>| <a href="http://ytsp88.com" target="_blank">޹ŮƵ</a>| <a href="http://www876444.com" target="_blank">޹Ʒ߹ۿ</a>| <a href="http://www132126.com" target="_blank">1134Ʒâ</a>| <a href="http://zhaosaohuo.com" target="_blank">޶·Ļ߿</a>| <a href="http://941sese.com" target="_blank">߲˳Ƶվ</a>| <a href="http://yiren2233.com" target="_blank">+ۺ+</a>| <a href="http://bjdxpx.com" target="_blank">Ʒ߹ۿ</a>| <a href="http://m8va.com" target="_blank">³ѲƵ㽶</a>| <a href="http://5g6z.com" target="_blank">ؼaaaaaaaaaëƬƵ</a>| <a href="http://yy6090qpgdy.com" target="_blank">պһƬѹۿ</a>| <a href="http://lanoss.com" target="_blank">eeussӰԺ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>