首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > JavaScript >

JSTL入门:访问sql跟xml内容 (四)

2012-11-04 
JSTL入门:访问sql和xml内容 (四)Web应用程序的模板式(stereotypical)架构分为三层:处理请求的Web服务器、实

JSTL入门:访问sql和xml内容 (四)

Web应用程序的模板式(stereotypical)架构分为三层:处理请求的Web服务器、实施业务逻辑的应用程序服务器以及管理永久性数据的数据库。应用程序和数据库层之间的联接通常采用关系数据库中的SQL调用格式。当业务逻辑被写入到Java语言中时,JDBC用于实现这些调用。

如果应用程序调用与其它服务器(本地或远程)的集成,我们将需要用于在不同子系统之间交换数据的更深层次的机制。在Web应用程序内部和应用程序之间传送数据采用的越来越普遍的一种方法是XML文件的交换。

迄今为止,在我们的JSTL之旅中,我们讨论了JSTL 表达式语言(expression language,EL)和 core和 fmt标记库。在最后一部分,我们将考虑sql和xml库--正如它们的名字表示的一样 -- 提供定制标记来接入和管理从SQL数据库和XML文件检索到的数据。

name" scope=" scope" filter=" expression" systemId=" expression"/>

在这五种属性中,只有xml属性是需要的,其值应该是包含要分解的XML文件的字符串,或者是java.io.Reader实例,通过它可以读取要被分解的文件。此外,您可以使用以下语法,根据<x:parse>标记的主体内容来规定要被分解的文件:

?

scope" filter=" expression" systemId=" expression"> body content</x:parse>

var和scope属性规定存储分解后的文件的scoped变量。然后xml库中的其它标记可以使用这一变量来运行其它操作。注意,当var和 scope 属性存在时,JSTL用于表示分解后的文件的数据结构类型以实施为导向,从而厂商可以对其进行优化。

如果应用程序需要对JSTL提供的分解后的文件进行处理,它可以使用另一种格式的<x:parse>,它要求分解后的文件坚持使用一个标准接口。在这种情况下,该标记的语法如下:

?

name" scopeDom=" scope" filter=" expression" systemId=" expression"/>

当您使用<x:parse>的这一版本时,表示分解后的XML文件的对象必须使用org.w3c.dom.Document接口。当根据<x:parse>中的主体内容来规定XML文件时,您还可以使用varDom和scopeDom属性来代替var 和 scope属性,语法如下:

?

scope" filter=" expression" systemId=" expression"> body content</x:parse>

其它两个属性filter 和 systemId 可以实现对分解流程的精确控制。filter 属性规定org.xml.sax.XMLFilter类的一个实例,以在分解之前对文件进行过滤。如果要被分解的文件非常大,但目前的工作只需要处理一小部分内容时这一属性尤其有用。systemId属性表示要被分解的文件的URI并解析文件中出现的任何相关的路径。当被分解的XML文件使用相关的URL来引用分解流程中需要接入的其它文件或资源时需要这种属性

清单1展示了<x:parse> 标记的使用,包括与 <c:import>的交互。此处<c:import> 标记用于检索众所周知的Slashdot Web 网站的RDF Site Summary (RSS)反馈,然后使用<x:parse>分解表示RSS 反馈的XML文件,表示分解后的文件的以实施为导向的数据结构被保存到名为rss的变量(带有page 范围)中。


清单1:<x:parse>与<c:import>的交互

expression" var=" name" scope=" scope" xmlSystemId=" expression" xsltSystemId=" expression"> <x:param name=" expression" value=" expression"/> ...</x:transform>

?

此处,xml 属性规定要被转换的文件,xslt 属性规定定义这次转换的样式表。这两种属性是必要的,其它属性为可选。

与<x:parse>的xml属性一样,<x:transform>的xml 属性值可以是包含XML文件的字符串,或者是接入这类文件的Reader。此外,它还可以采用 org.w3c.dom.Document 类或javax.xml.transform.Source 类的实例格式。最后,它还可以是使用<x:parse> 操作的var或varDom属性分配的变量值。

而且,您可以根据<x:transform> 操作的主体内容来包含要被转换的XML文件。在这种情况下,<x:transform> 的语法是:

scope" xmlSystemId=" expression" xsltSystemId=" expression"> body content <x:param name=" expression" value=" expression"/> ...</x:transform>

在这两种情况下,规定XSL 样式表的xslt 属性应是字符串、Reader或javax.xml.transform.Source实例。

如果var 属性存在,转换后的XML文件将分配给相应的scoped变量,作为org.w3c.dom.Document 类的一个实例。通常,scope属性规定这类变量分配的范围。

<x:transform> 标记还支持将转换结果存储到javax.xml.transform.Result 类的一个实例中,而不是作为org.w3c.dom.Document的一个实例。如果var 和 scope 属性被省略,result对象规定作为result属性的值,<x:transform>标记将使用该对象来保存应用该样式表的结果。清单2中介绍了使用<x:transform> 的result属性的这两种语法的变化:


清单2:使用result属性来提供javax.xml.transform.Result实例时,<x:transform>操作的语法变化

expression" result=" expression" xmlSystemId=" expression" xsltSystemId=" expression"> <x:param name=" expression" value=" expression"/> ...</x:transform><x:transform xslt=" expression" result=" expression" xmlSystemId=" expression" xsltSystemId=" expression"> body content <x:param name=" expression" value=" expression"/> ...</x:transform>

无论您采用这两种<x:transform>格式中的那一种,您都必须从定制标记单独创建javax.xml.transform.Result对象。该对象自身作为result属性的值提供。

如果既不存在var 属性,也不存在result属性,转换的结果将简单地插入到JSP页面,作为处理<x:transform> 操作的结果。当样式表用于将数据从XML转换成HTML时尤其有用,如清单3所示:


清单3:在JSP页面直接显示转换的XML数据

在本例中,使用 <c:import> 标记来读取RSS反馈和适当的样式表。样式表的输出结果是HTML,通过忽略<x:transform>的var和result 属性来直接显示。

?

与<x:parse>的systemId 属性一样,<x:transform>的xmlSystemId 和 xsltSystemId 属性用于解析XML文件中相关的路径。在这种情况下,xmlSystemId 属性应用于根据标记的 xml属性值提供的文件,而xsltSystemId 属性用于解析根据标记的xslt属性规定的样式表中的相关路径。

如果正在推动文件转换的样式表使用了参数,我们使用<x:param> 标记来规定这些参数。如果参数存在,那么这些标记必须在<x:transform> 标记主体内显示。如果根据主体内容规定了要被转换的XML文件,那么它必须先于任何 <x:param> 标记。

<x:param> 标记有两种必要的属性 -- name 和 value -- 就象本系列 第2部分 和 第3部分中讨论的<c:param> 和 <fmt:param> 标记一样。

boolean"/>

当然,两者的区别在于<x:out> 的select 属性值必须是XPath表达式,而<c:out> 的value 属性必须是EL表达式。两种标记的escapeXml 属性的意义是相同的。

清单4显示了<x:out> 操作的使用。注意,规定用于select 属性的XPath表达式由一个EL表达式规定为scoped变量,尤其是$rss。这一EL表达式根据将被求值的XPath语句来识别分解后的XML文件。该语句在此处查找名为title且父节点名为channel的Element,从而选择它找到的第一个Element(根据表达式尾部[1]索引规定)。这一<x:out> 操作的结果是显示这一Element的主体内容,关闭正在转义(Escaping)的XML字符。


清单4:使用<x:out>操作来显示XML Element的主体内容

除了<x:out>之外,JSTL xml 库包括以下控制XML数据的标记:

<x:set> ,向JSTL scoped 变量分配XPath表达式的值 <x:if> ,根据XPath表达式的布尔值来条件化内容 <x:choose>、<x:when>和<x:otherwise>,根据XPath表达式来实施互斥的条件化 <x:forEach> ,迭代根据XPath表达式匹配的多个Elements

每个这些标记的操作与core库中相应的标记类似。例如,清单5中显示的<x:forEach>的使用, <x:forEach> 操作用于迭代XML文件中表示RSS反馈的所有名为item 的Element。注意,<x:forEach>主体内容中嵌套的两个<x:out> 操作中的XPath表达式与<x:forEach>标记正在迭代的节点相关。它们用于检索每个item element的子节点link 和 title。


清单5:使用<x:out> 和<x:forEach>操作来选择和显示XML数据

清单5中JSP程序代码的输出结果与 清单3类似。xml 库以XPath为导向的标记提供备选的样式表来转换XML内容,尤其是当最后的输出结果是HTML的情况。

?

scope"/><sql:setDataSource url=" expression" driver=" expression" user=" expression" password=" expression" var=" name" scope=" scope"/>

第一种格式只需要dataSource 属性,而第二种格式只需要url 属性。

通过提供JNDI名作为dataSource属性值,您可以使用第一种格式来接入与JNDI名相关的datasource。第二种格式将创建新的datasource,使用作为url属性值提供的JDBC URL。可选的driver 属性规定实施数据库driver的类的名称,同时需要时user 和 password 属性提供接入数据库的登录证书。

对于<sql:setDataSource>的任何一种格式而言,可选的var 和 scope 属性向scoped变量分配特定的datasource。如果var属性不存在,那么 <sql:setDataSource> 操作设置供sql 标记使用的缺省 datasource,它们没有规定明确的datasource。

您还可以使用javax.servlet.jsp.jstl.sql.dataSource 参数来配置sql 库的缺省datasource。在实践中,在应用程序的Web.xml文件中添加与清单6中显示的类似的程序代码是规定缺省datasource最方便的方式。使用<sql:setDataSource> 来完成这一操作要求使用JSP页面来初始化该应用程序,因此可以以某种方式自动运行这一页面。


清单6:使用JNDI名来设置JSTL在web.xml部署描述符中的缺省datasource

expression" var=" name" scope=" scope" maxRows=" expression" startRow=" expression"/><sql:query sql=" expression" dataSource=" expression" var=" name" scope=" scope" maxRows=" expression" startRow=" expression"> <sql:param value=" expression"/> ...</sql:query><sql:query dataSource=" expression" var=" name" scope=" scope" maxRows=" expression" startRow=" expression"> SQL statement <sql:param value=" expression"/> ...</sql:query>

前两种格式只要求sql 和 var 属性,第三种格式只要求var 属性。

var 和 scope 属性规定存储查询结果的scoped 变量。maxRows 属性可以用于限制查询返回的行数,startRow 属性允许忽略一些最开始的行数(如当结果集(Result set)由数据库来构建时忽略)。

在执行了查询之后,结果集被分配给scoped变量,作为javax.servlet.jsp.jstl.sql.Result 接口的一个实例。这一对象提供接入行、列名称和查询的结果集大小的属性,如表1所示:

在<sql:query> 操作中,SQL语句根据主体内容来规定,或者使用?字符,通过sql 属性实现参数化。对于SQL语句中每个这样的参数来说,应有相应的<sql:param> 或 <sql:dateParam> 操作嵌套到<sql:query> 标记的主体中。<sql:param> 标记只采用一种属性 -- value --来规定参数值。此外,当参数值为字符串时,您可以忽略value 属性并根据<sql:param> 标记的主体内容来提供参数值。

表示日期、时间或时间戳的参数值使用<sql:dateParam> 标记来规定,使用以下语法:

type"/>

?

对于<sql:dateParam>来说,value 属性的表达式必须求 java.util.Date 类实例的值,同时type 属性值必须是date、time或timestamp,由SQL语句需要那类与时间相关的值来决定。

与<sql:query> 一样,<sql:update> 操作支持三种格式:

expression" var=" name" scope=" scope"/><sql:update sql=" expression" dataSource=" expression" var=" name" scope=" scope"> <sql:param value=" expression"/> ...</sql:update><sql:update dataSource=" expression" var=" name" scope=" scope"> SQL statement <sql:param value=" expression"/> ...</sql:update>

?

sql 和dataSource 属性有与<sql:query>相同的<sql:update> 语义。同样,var 和 scope 属性可以用于规定scoped变量,但在这种情况下,分配给scoped变量的值将是java.lang.Integer 的一个实例,显示作为数据库更新结果而更改的行数。

isolationLevel"> <sql:query .../> or <sql:update .../> ...

?

<sql:transaction> 操作没有必需的属性。如果您忽略了dataSource 属性,那么使用JSTL的缺省datasource。isolation 属性用于规定事务处理的隔离级别,它可以是read_committed、read_uncommitted、repeatable_read或serializable。如果您未规定这一属性,事务处理将使用datasource的缺省隔离级别。

您可能希望所有嵌套的查询和更新必须使用与事务处理相同的datasource。实际上,嵌套到<sql:transaction>操作中的<sql:query> 或 <sql:update> 不能用于规定dataSource 属性。它将自动使用与周围的<sql:transaction>标记相关的datasource (显性或隐性)。

清单8显示了如何使用<sql:transaction> 的一个实例:


清单:使用<sql:transaction>来将数据库更新联合到事务处理中


JSTL入门:访问sql跟xml内容 (四)

?


JSTL入门:访问sql跟xml内容 (四)


结束语

在本系列中,我们讨论了4个JSTL定制标记库的功能及它们的使用。在 第1部分 和 第2部分,我们讨论通过El和core 库标记的使用,您如何在许多常见情况下避免JSP脚本程序。 第3部分 关注使用fmt 库来本地化Web内容。

在最后一部分,我们讨论了xml 和 sql 库的功能。如果您愿意接受将业务逻辑包含到表示层的结果,这两个库中的标记都使其能够非常轻松地将XML文件和关系数据库中的内容结合到JSP页面。这两个库还展示了当集成<sql:query> 和<c:forEach>时,JSTL库如何构建和集成,以及xml 库利用<c:import> 操作的能力。

热点排行