cocoon系列 —— XML Server Pages(XSP) 笔记

cocoon系列 —— XML Server Pages(XSP) 笔记

XML Server PagesXSP 笔记

1、基本概念

XSP可以将动态数据添加到XML 文档中以创建更丰富的网站,也可以使 Cocoon 2 集成现有数据源和/或 API 以在因特网上用多种格式发布数据。它是一种能够创建动态 XML 数据源以便将数据传输到 Cocoon 2 管道的 Cocoon 2 技术。通过使用 XML 标记和应用逻辑的组合来描述这些数据源,然后由 Cocoon 2 引擎自动将这种组合编译为 Java 类。XSP 为使用 Cocoon 2 开发应用程序提供了一个灵活的平台。例如,Cocoon 2 应用程序可以显示现有应用程序数据库中的信息,而且启用了更为多样的数据发送选项。通过提供一种通过 XML 界面显示数据源的方法,XSP 允许在诸如中间件和文档发布那样的应用程序集成环境中使用 Cocoon 2。

1.1 XSP 与 JSP

1.1.1相同点:

1)由程序代码和标记的混合体组成

2)被编译成用于执行的二进制形式

3)允许创建定制标记库

1.1.2不同点:

1) XSP 为将任何编程语言中的代码与 XML 标记混合在一起提供了一个框架。

2) XSP 生成动态数据

XSP 生成动态数据,而不是动态表示。与之不同,JSP 则是一种通常用于在一系列处理步骤的最后阶段产生 HTML 或 XML 的表示层技术。XSP 页面为 Cocoon 管道生成 XML 数据,而由管道创建了所期望的表示。

 

1.2 XSP 编译过程

  1. 解析 XSP 文档
  2. 通过使用专用 XSLT 样式表转换 XSP 页面,以生成 Java 源代码
  3. 通过使用代码格式化器,在整齐地缩排和格式化源代码后,存储结果 Java 文件
  4. 将源代码编译成生成器
  5. 在请求管道中装入并执行已编译的生成器

 

1.3 一个XSP运行例子

Cocoon 2 提供了一个协调个别 XSP 页面的编译和执行的 ServerPagesGenerator 组件。在网站地图中,ServerPagesGenerator 声明如下:

<map:generators default="file"> 
   <map:generator  name="xsp" src="org.apache.cocoon.generation.ServerPagesGenerator"/> 
   <!-- ... other generator declarations ... --> 
</map:generators> 

要在管道中使用这个生成器,只须简单声明应当使用(而不是缺省值)并且指出在何处可以找到特定的 XSP 页面的源代码,如下所示:

<map:pipeline> 
   <map:match pattern="tutorial/*.xml"> 
      <map:generate type="xsp" src="tutorial/{1}.xsp"/> 
      <map:serialize type="xml"/> 
   </map:match> 
</map:pipeline> 

 

2、语法

2.1 xsp:page 元素

xsp:page 元素是每个 XSP 文档的根元素。
   
<xsp:page language="java" xmlns:xsp="http://apache.org/xsp"> 
   <!-- page contents --> 
</xsp:page> 

2.2 xsp:structure 和 xsp:include 元素

当添加利用标准或定制 Java API 的编程逻辑时,必须在 XSP 中指出生成的源代码中需要另外的 import 语句以确保编译成功地完成。xsp:structurexsp:include 元素用于向代码生成过程提供这些附加提示。

<xsp:page language="java" xmlns:xsp="http://apache.org/xsp"> 
   <xsp:structure> 
      <xsp:include>java.util.Calendar</xsp:include> 
      <xsp:include>java.text.*</xsp:include> 
   </xsp:structure> 
   <!-- page contents --> 
</xsp:page> 
  

2.3 xsp:logic 元素

xsp:logic 元素用于将 Java 代码块添加到 XSP。例如:

<xsp:page language="java" xmlns:xsp="http://apache.org/xsp"> 
   <xsp:logic> 
      public String getTime() 
      { 
         return java.util.Calendar.getInstance().getTime().toString(); 
      } 
   </xsp:logic> 
   <document/> 
</xsp:page> 

 

<xsp:page language="java" xmlns:xsp="http://apache.org/xsp"> 
   <document> 
      <xsp:logic> 
         SimpleDateFormat format = new SimpleDateFormat("EEE, MMM d, yyyy"); 
         String timestamp = format.format( 
                                   java.util.Calendar.getInstance().getTime() 
                                   ); 
      </xsp:logic> 
      <time><xsp:expr>timestamp</xsp:expr></time> 
      <!-- additional elements --> 
   </document> 
</xsp:page>               
   

这个代码包含了对 XSP 文档求值时创建时间戳记的逻辑。然后通过使用 xsp:expr,这个时间戳记被添加到了 time 元素内的文档中。

2.4 避免错误,保持良好的格式

2.4.1 程序代码与 XML 标记

if (a < b && c > d) { ... }改为①if (a &lt; b &amp;&amp; c &gt;) { ... }或者② 
<xsp:logic> 
   <![CDATA[ 
      if (a < b && c > d) { ... } 
   ]]&gt; 
</xsp:logic> 
但是②将忽略这些节内出现的任何 XSP 或用户元素,而将它们当作纯文本而不是 XML 标记进行处理,这样更可能导致隐蔽的、耗时的错误。 

2.4.2 xsp:logic 元素内 XML格式规则

以下有错:

<search-results> 
   <xsp:logic> 
      if (firstResult()) 
      { 
         <result id="first"> 
      } else 
      { 
         <result> 
      } 
         <!-- ...result generation code here... --> 
      </result> 
   </xsp:logic> 
</search-results> 
应改为 
<search-results> 
   <xsp:logic> 
      if (firstResult()) 
      { 
         <result id="first"> 
            <!--... handle first result..--> 
         </result> 
      } else 
      { 
         <result> 
            <!--...handle other results...--> 
         </result> 
      } 
   </xsp:logic> 
</search-results> 
  

2.5 xsp:expr 元素

xsp:expr 元素等价于在 JSP 中实现类似角色的 <%= ... %> 表达式语法。
   
<elements> 
   <xsp:logic> 
      for (int i=1; i<11; i++) 
      { 
         <element><xsp:expr>i</xsp:expr></element> 
      } 
   </xsp:logic> 
</elements> 

2.6 通过使用 xsp:element 生成动态元素

通过使用 xsp:element,还可以动态地创建元素,它的工作原理类似于其 XSLT 等价机制的工作原理。

<xsp:element> 
   <xsp:param name="name"><xsp:expr>"myElementName"</xsp:expr></xsp:param> 
   Element content 
</xsp:element> 

还可以与一个特定的名称空间和前缀关联

<xsp:element prefix="my" uri="http://www.examples.org"> 
   <xsp:param name="name"><xsp:expr>"myElementName"</xsp:expr></xsp:param> 
   Element content 
</xsp:element> 

这个示例生成了以下 XML 输出:

<my:myElementName xmlns:my="http://www.examples.org">Element content</my:myElementName>

还可能动态地生成名称空间 URI 和前缀。无须添加 prefixuri 属性,而是使用带适当名称的附加 xsp:param 元素。下列代码等价于上面的示例:

<xsp:element prefix="my" uri="http://www.examples.org"> 
   <xsp:param name="name"><xsp:expr>"myElementName"</xsp:expr></xsp:param> 
   <xsp:param name="prefix">"my"</xsp:param> 
   <xsp:param name="uri">"http://www.examples.org"</xsp:param> 
   Element content 
</xsp:element> 

2.7 通过使用 xsp:attribute 生成动态属性

xsp:attribute 元素的工作原理类似于 xsp:element,它允许动态创建属性的名称及其值:

<xsp:element> 
   <xsp:param name="name"><xsp:expr>"myElementName"</xsp:expr></xsp:param> 
   <xsp:attribute name="myAttribute">myAttributeValue</xsp:attribute> 
   Element content 
</xsp:element> 

这个属性的名称定义在 name 属性内,尽管是用与 xsp:element 类似的方法定义的,但它还能通过使用 xsp:param 子元素来定义。属性值被指定成元素内容。这可以是一个简单文本值或更有效地由 xsp:expr 元素生成。

2.8 创建注释和处理指令

2.8.1 创建注释:

<xsp:comment>This is a comment</xsp:comment>               
   

然后这个注释变成:

<!-- This is a comment --> 

2.8.2 创建处理指令类似于创建动态元素或属性:

<xsp:pi target="myApplication"> 
   <xsp:expr>"param1=value, param2=value, generatorTimestamp=" + 
   System.currentTimeMillis()</xsp:expr> 
</xsp:pi>               
   

输出如下:

<?myApplication param1=value, param2=value, generatorTimestamp=1017407796870?>            
   

还可以通过在 xsp:param 元素内创建处理指令的目标来自动生成它,如同以下示例演示的那样:

<xsp:pi> 
   <xsp:param name="target"><xsp:expr>"myApplication"</xsp:expr></xsp:param> 
   <xsp:expr>"param1=value, param2=value, generatorTimestamp=" + 
   System.currentTimeMillis()</xsp:expr> 
</xsp:pi> 
  

3 逻辑单

逻辑单是能被钩接入代码生成过程以允许创建定制标记库的 XSLT 转换。这些逻辑单使 XSP 页面更容易处理,从而减少了直接嵌入代码的需要。

3.1 使用逻辑单

每个逻辑单都与一个特殊的名称空间关联。使用逻辑单仅仅涉及在 XSP 文档中声明相应的名称空间,然后在需要的时候添加来自那个名称空间的元素。

 

<xsp:page language="java" 
         xmlns:xsp="http://apache.org/xsp" 
         xmlns:util="http://apache.org/xsp/util/2.0"> 
   <clock> 
      <day><util:time format="EE"/></day> 
      <month><util:time format="MMMM"/></month> 
      <year><util:time format="yyyy"/></year> 
      <time><util:time format="HH:mm:ss 'on' dd/MM/yyyy"/></time> 
   </clock> 
</xsp:page> 

3.2内置逻辑单

3.2.1 环境逻辑单

在这个环境类别中有四个逻辑单,每个逻辑单都提供对与 Web 请求关联的处理环境的特殊方面的访问。这些逻辑单提供的功能类似于与 JSP 页面关联的隐式对象(例如,requestresponse 对象)提供的功能,并且是从 HTTP Servlet API 中直接提取的。

1) 请求(request)逻辑单

提供了对请求属性的访问,包括对请求参数、请求方法(例如,GETPOST 等等)以及请求标题的访问。当请求参数的某些方面用于改变输出文档的生成时,这个逻辑单就格外有用。

2)响应(response)逻辑单

提供对与当前请求关联的 HTTP 响应的限制访问;它只提供对请求标题的访问。XSP 文档不能用与 Java Servlet 或 JSP 页面相同的方法执行包含或转发,因为分离问题是 Cocoon 2 体系结构的核心部分。这个功能描述在网站地图中;XSP 页面生成 XML 内容而不指导处理。

3)会话(session)逻辑单

提供了对 HTTP 会话信息的访问,包括创建和删除会话以及添加和除去会话属性的能力。很明显,这个功能在必须为上下文维护用户会话的 Web 应用程序中是最有用的。Cocoon 2 中的会话管理正好等价于它的 JSP 对手。

4)cookie 逻辑单

提供了 cookie 维护功能,诸如添加和除去 cookie、允许优先存储到用户的浏览器中。

3.2.2 实用程序逻辑单

1) 日志(log)逻辑单

<xsp:page language="java"  xmlns:xsp="http://apache.org/xsp" 
         xmlns:util="http://apache.org/xsp/log/2.0"> 
   <log:debug>This is a debug message from an XSP generator</log:debug> 

</xsp:page>

2) 发送邮件(sendmail) 逻辑单

<sendmail:send-mail from="[email protected]" to="[email protected]" smtphost="[email protected]"> 
   <xsp:param name="subject"><xsp:expr>"The subject of this email..."</xsp:expr></xsp:param> 
   <xsp:param name="body"><xsp:expr>"The body of this email..."</xsp:expr></xsp:param> 
</sendmail:send-mail> 

3) 时间逻辑单

如前面的示例。

3.2.3 数据操作

1) 表单验证器(form validator)逻辑单

表单验证器(form validator)逻辑单从未真正单独使用。它向 Cocoon 表单验证器行为(Cocoon Form Validator Action)提供一个整齐的界面。这个行为能够对从 HTML 表单发送到 Cocoon 应用程序的数据执行基本验证操作,包括检查整数的最小和最大值、检查字符串的大小以及检查提供的某些参数。一个著名功能是能够测试传递的变量是否匹配给定的正则表达式。

2) esql 逻辑单

esql 逻辑单提供了执行这一步的方法,并提供了更多的功能,包括选择、删除和更新数据库。本质上,esql 逻辑单提供了将 SQL 语句直接嵌入到 XSP 文档的方法。然后这个逻辑单生成相应的 JDBC 代码来实现 SQL 操作,这样通过使用 Cocoon 2 简化了对数据库数据的操作和检索。

3.3 编写逻辑单

因为逻辑单转换可能以任何顺序发生,所以每个逻辑单都需要保留输入文档中它不理解的任何内容。换句话说,逻辑单的基本模板是恒等转换。这是一个将它的输入未做更改而直接简单复制到它的输出的转换。

<xsl:template match="time:time"> 
   <xsp:logic> 
      SimpleDateFormat timeFormat = new SimpleDateFormat("<xsl:value-of select="@format"/>"); 
   </xsp:logic> 
   <xsp:expr> 
      timeFormat.format(java.util.Calendar.getInstance().getTime()) 
   </xsp:expr> 
</xsl:template>               
   

该单一模板与 time 元素匹配,并用封装在 xsp:logicxsp:expr 元素中的代码来替代它们以创建日期。所需的日期格式由用户通过这个元素上的 format 属性来说明。

3.4 配置逻辑单

在该配置文件中搜索 xsp-language 元素,并注意它包含一个名为 target-language 的子元素。应声明这个元素内的所有逻辑单。还可能看到已预先定义了内置逻辑单。这里是 util 逻辑单的项:

<builtin-logicsheet> 
   <parameter name="prefix" value="util"/> 
   <parameter name="uri" value="http://apache.org/xsp/util/2.0"/> 
   <parameter name="href" value="resource://org/apache/cocoon/components/language/markup/xsp/java/util.xsl"/> 
</builtin-logicsheet> 

另例如:

     <!--*************** Test By David *************** -->

        <builtin-logicsheet>

          <parameter name="prefix" value="xsp-time"/>

          <parameter  name="uri" value="$CATALINA_HOME/webapps/cocoon/WEB-INF/classes/logicsheets/time.xsl"/>

          <parameter name="href" value="resource://logicsheets/time.xsl"/>

        </builtin-logicsheet>

3.5 逻辑单的开发技巧

3.5.1 使用助手类:

虽然创建逻辑单将从 XSP 页面中提取出程序代码,但这个代码仍被锁藏在 XSLT 样式表中。这使不依赖 Cocoon 而要维护和测试代码很困难。一个好的设计技巧是将尽可能多的代码放入助手类中。这样使得逻辑单的实现简化为只是收集参数,然后调用所需的助手方法。内置逻辑单遵循这个指南,并且每个逻辑单都有单个助手类。

3.5.2 创建逻辑单“宏”

宏是记录和重新执行一系列操作的一个简单快速的方法。在特殊应用程序中的 XSP 页面可能要重复创建相同的 XML 结构或用同样的方法调用其它逻辑单。提取出 XSP 页面中的公共块,以创建描述这个重复结构的较高级别元素(例如,宏)是很有用的。因为 Cocoon 2 递归地应用逻辑单,直到处理完所有名称空间为止,一个逻辑单的实现可以添加另一个逻辑单上的元素。这种组合可以大大降低 XSP 页面的复杂程度。

3.5.3 考虑用户

当考虑在逻辑单中提供什么样的标记时,请考虑最终用户。他们需要怎样的灵活性?例如,可以将什么样的参数发送给标记?只能通过属性或嵌套的 xsp:param 元素发送参数吗?后者更加灵活,因为它允许用户通过使用 xsp:expr 动态地创建参数值,而 xsp:expr 不能在属性内使用。还要考虑如何命名标记。赋予它一个清晰和好记的名称,这样它所做的就显而易见了。并不是每个人都乐意深入研究逻辑单的实现来感受这一点的。这个建议的一个很明显扩展是向逻辑单提供支持文档;这使用户能快速找到标记的含义以及如何使用它。

 

你可能感兴趣的:(cocoon系列 —— XML Server Pages(XSP) 笔记)