- 浏览: 392516 次
-
文章分类
最新评论
-
小尜:
写的很详细,也很简单,一看就懂。多谢啦。
关于工厂模式和spring的IOC -
fjjiaboming:
代码排版!!!!!
JDBC事务和JTA (XA)事务 -
fjjiaboming:
排版有问题吗? 望交流.
做人有三个层次 -
fjjiaboming:
看来数据库连接池 必须用JNDI 注册在容器 , 对吗?
JDBC事务和JTA (XA)事务 -
fd1803:
SSL工作原理:http://www.wosign.com/B ...
SSL(Server Socket Layer)简介
使用JSTL改进JSP来简化网页的实现过程:
概述
Java Server Pages (JSP) 标准标记库 (JSTL)的版本的发布对于JSP/servlet开发者来说是一个重大的进展。有了一个表达语言(EL)和一组四种强大的、易于学习的标准标记库,JSTL极有可能不久后成为实现动态的、基于Java的站点的主要方法。
1996年对JSP servlet的介绍使得Java成为动态网页开发的合理的选择。随后出现的Java服务器页(JSP)是走向快速的、可维护的Java网页实现过程的合理进化的一步,紧接着就出现了JSP标记的支持。但是2002中期的JSTL(JSP标准标记库)的发布才是进一步加速和简化开发过程最大的一步。
在本文中,我解释了JSTL的功能,也涵盖了你启动JSTL所需的每件事情。假设你有了对Java、JSP、XML和安装一个Web容器的基本理解。如果你对这些主题感到陌生,你可以在Resources(http://www.javaworld.com/javaworld/jw-02-2003/jw-0228-jstl.html?#resourcesresources)上浏览一下背景参考。在下面的阐述中,假定你有XML和SQL的知识。
安装JSTL支持
对于我们的JSTL安装例子来说,我们使用Tomcat 4.1(尽管任意支持Servlet 2.3和JSP1.2说明的servlet容器都应该能工作)。首先,下载Tomcat 4.1并且按指示进行安装(注意:JSTL需要一个JSP1.2 Web容器)。
用tomcat4 start程序启动Tomcat,并且运行index.html页来确保Tomcat是激活的、且运行良好。
接下来,安装JSTL支持,你可以从Jakarta站点下载JSTL支持,(http://www.javaworld.com/javaworld/jw-02-2003/jw-0228-jstl.html?#resourcesresources)并按照下面步骤:
1.从Jakarta站点下载JSTL检索、解压/脱档该文件。(http://www.javaworld.com/javaworld/jw-02-2003/jw-0228-jstl.html?#resources)
2.复制你已经解压为common/lib的jar文件到你的Tomcat安装路径中(尽管我们的项目不需要所有的jar文件);这使得JSTL文件适用于你的任意Web应用。
3.对于任意你想使用JSTL的Web应用来说,复制.tld文件到你的Web应用的WEB-INF目录下。
4.对于你的JSTL的Web应用,编辑web.xml并添加下列输入:
<taglib> <taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri> <taglib-location>/WEB-INF/fmt.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://java.sun.com/jstl/core</taglib-uri> <taglib-location>/WEB-INF/c.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://java.sun.com/jstl/sql</taglib-uri> <taglib-location>/WEB-INF/sql.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://java.sun.com/jstl/x</taglib-uri> <taglib-location>/WEB-INF/x.tld</taglib-location> </taglib> |
这些输入让你的Web应用可使用JSTL标记库的表达语言(EL)版本。这些输入的位置有关系!如果你不肯定将他们输入到何处,关于web.xml选项和顺序的权威性指导在文档类型定义(DTD)中定义过:http://java.sun.com/j2ee/dtds/web-app_2_2.dtd。
5.当你创建了一个使用JSTL的JSP页时,将他输入到你的Web应用的主目录下,就像其它JSP和HTML页一样。你可以为该页任意取名,但是它必须有一个.jsp的扩展名。
基础原理
首先,所有的JSTL也是JSP页,JSTL只是JSP功能的一个超集。
同样,所有的JSTL标记是有效的XML。这意味着:如果你将JSTL标记之外的内容当作临时文本(通常是HTML)时,剩下的JSTL标记必须当作合法的XML来解释。这里有一些隐含的规则,它要求大部分XML语法都是正确的。
JSTL提供一组四个标准标记库(core核心、internationalization/format国际标准化/格式、XML和SQL)并支持EL。JSTL和EL的基本设计目的是简化网页开发和实现。
在本文中,我们遵循JSTL说明书的命名规则,并且把JSTL标记当作动作。一个JSTL标记对应于某个动作;调用动作明确的提醒我们:他们添加动态行为到一个另外的静态页上。
JSTL标记库有两个版本:一个用你以前使用的方法将JSP表达式插入,如<%= . . . %>,另一个使用一个JSTL EL.我会在后面进一步讨论在JSTL中的EL支持。
EL支持
要理解当前JSTL对EL支持的状态,让我们检查相关的说明书是怎样处理的。Java说明书请求(JSR)专家组成员决定:由于某种原因,EL规范说明应该是JSP说明书的一部份,而不是JSTL说明书的一部分。EL完整的说明书成为JSP2.0的一部分。因为JSTL1.0在JSP1.3之前已经完成,JSTL作者不得不对用于JSTL1.0的EL支持实现做一个合理的猜测(结果可能是相当好的)。一个JSTL维护版本将与JSP1.3说明书保持一致,并为了使EL适合JSP1.3说明书,JSTL维护版本做了一些修正。
本文描述的EL概要可能在即将发布的JSTL版本中有一点改动,但是任何改动都是微小的。
EL用于简单的语法定义了一套功能强大的语言,它很容易学习。它融合着JavaScript语言和Perl语言较好的部分的一些风格。EL表达式,集成了来自四种标准标记库的JSTL标记,提供了一个巨大的、灵活的属性集。
所有的EL表达式都被${}括起来。JSTL中的表达式总是JSTL标记中的属性值的一部分。表达式可以是属性的一部分或者合并和嵌入到一个字符串直接量中。JSTL属性也可以包含简单的字符串直接量。在接下来的JSTL中,我们在一个来自核心库的c:out动作中说明每种情况,这个核心库将它的value属性值送到JSP输出上:
<c:out value="${anExpression}"/> <c:out value="literalText${anExpression}${anotherExpression}"/> <c:out value="literalText"/> |
EL也定义了一套规则用于强制表达式中的值转换为上下文相对应的类型。我们在这里不详细讨论这些规则;然而,它的方法与用Perl语言定义的方式非常相似(就像Perl语言中的做法一样,该方法理所当然的运行良好,但是,偶尔,也会出现可能不是你十分想要的那种结果,但你可以接受)。
EL为访问对象属性、集合元素、一组隐藏对象以及使用相关的、逻辑的和算术的操作符提供了支持。对于索引的属性来说,包括数组和java.util.List类在内,元素可用下列语法访问:
${alist[4]} ${aList[someVariable]} |
JavaBean属性和java.util.Map元素(它代表一系列名字/值对)都可以使用下列方法的一个访问得到。在以下的开头两个表达式里,我们可以访问到一个用JavaBean语言命名为aProperty的属性或者用关键字aProperty访问到一个Map实体。在第三个表达式中(注意:我已经省略了引号),我们用保存在变量aVariableContainingPropertyName中的一个名字访问了在anObject之内的一个元素:
${anObject.aProperty} ${anObject["aPropertyName"]} ${anObject[aVariableContainingPropertyName]} |
在EL中定义了许多隐藏变量:
● pageContext:用于该网页的pageContext对象
● pageScope, requestScope, sessionScope, 和 applicationScope:这些是映射这些范围的每一个变量到值上的Map集。
● param 和 paramValues:用页访问传递的参数,与在JSP中一样
● header 和 headerValues:用页请求传递的头,与在JSP中一样
● cookie:Map映射cookie程序到特定的cookie对象上
EL定义了全套与你在Java中非常熟悉的那些完全对应的操作符。算法操作符包括 、 -、 *、 / (或 div)、 和% (或 mod)。相关的操作符包括==、!=、<、>、<=、>=,它分别对应于eq、ne、lt、gt、le、和ge。我不想详细阐述这些操作符,因为他们都能自我说明。
JSTL标记库
至此,我已经解释了一些基本原理并且涵盖了EL语法。我要专门讨论四种JSTL标记库。我主要讨论核心库,因为它是你一定要使用的;但是,我也会详细的讨论其余几个,以便你能启动它。
首先,尽管我应该更多地谈论JSTL标记库的两种风格,我上面提到的每个JSTL标记库以两个版本出现:一个支持使用EL的表达式;另一个支持标准JSP表达式。当你引入任何标记库到一个JSP页时,你要定义一个前缀,该前缀指定了与库中标记相对应的命名空间。
四种标准标记库,和他们的JSTL规范定义的前缀常规,列表如下。记住:你可以定义自己的前缀,但是这绝对没有什么好处。

为了使用页中的核心标记库( 实际上,你使你的页对标记库的命名空间可见),在你的页首包含下列例子中的指令:
<%@ taglib prefix="c" uri=http://java.sun.com/jstl/core %> |
为了使用该标记库的标记,用你在你的包含语句中设计好的前缀,在你的页中给每个标记加上前缀:
<c:out value="${anExpression}"/> |
核心数据库
让我们更详细的测试核心数据库,先看看他最通用的功能。
显示/设定值和异常处理
核心库的最基本的标记是c:out标记,它在页中显示一个EL表达式的值。一个使用c:out的表达式通常是这样:
We have <c:out value="${applicationScope.product.inventoryCount}" escapeXml="true" default="0" /> of those items in stock. |
上例中,value属性是我们送到页输出的表达式。我也说明了选项escapeXml的属性和默认属性。escapeXml的属性指定了XML字符(<、>、 &、 和 .)是否应该转化为相应的字符实体代码(这样他们可以让这些字符出现在一个HTML页中);默认属性用于EL不能估算出数值或者数值计算出来为空的情况。
注意:当EL支持完全贯穿整个JSP2.0的时候,你不需要使用c:out动作;你可以仅嵌套JSP表达式直接在页中。
另一个普遍使用的核心动作是c:set,它在页中设定一个变量。你可以用两种方法使用c:set动作,第一种方法设定在var属性中定义的变量到在value属性中定义的值上,方法如下:
<c:set var="customerID" value="$param:customerNumber" scope="session" /> |
上述的选择项scope属性指定了我们要在会话期范围内设定变量customerID;如果范围没有制定,范围默认为页。
c:set另一个强大的用途就是将c:set标记的体的内容赋给一个指定的变量:
<c:set var="cellContents"> <td> <c:out value="${myCell}"/> </td> </c:set> |
在上例中,c:set动作定义了名为cellContents(在页的范围内)的变量,该变量拥有在标记的体中定义的内容。在这种情况下,体定义了一个HTML表格单元格元素,计算体中的c:out动作,并且该计算的结果包括在体中的字符串直接量值。
就像你预想的那样,JSTL进行异常处理有点早。在典型的JSP页中,你有两种异常处理的方法:试图/捕捉直接嵌入到页中的小脚本代码中的块;或者用一个JSP errorPage指令。JSP errorPage指令提供一个良好的捕捉所有异常的方法来处理页中任何可能的异常。JSTL用一个c:catch动作提供一个好的可选择的方式。这个c:catch动作提供一个更细粒度的有效方法来处理异常。而且没有嵌入Java代码到页中。一个c:catch动作是这样的:
<c:catch> <!--. . . some set of nested JSTL tags below which would be hit on an exception--> </c:catch> |
c:catch动作有一个可选的属性,即一个指向抛出异常的变量。
你可能不怎么愿意使用c:remove标记。这个标记有用于变量名和范围的属性,并且可从指定的范围内删除指定的变量。
流程控制
让我们转为讨论JSTL的流程控制和条件标记。如果你已经用任何一种语言使用了条件和流程控制语句,理论上这里没什么新鲜的东西。
c:if动作处理简单条件语句的测试。计算测试属性中的Boolean表达式的值,如果表达式为真的话,计算体的内容。在下面的动作中,我们也说明了备选项var属性。为了以后的使用,var属性保存测试结果在页(如果没有指定其他scope属性的话)中。
<c:if test="${status.totalVisits == 1000000}" var="visits"> You are the millionth visitor to our site! Congratulations! </c:if> |
下面我们展示了用c:choose、 c:when、 和 c:otherwise交换逻辑的JSTL的支持。一组c:when动作可能包括在一个备选的标记内,如果在c:when块中任何表达式计算值为真的话,就不用计算c:choose动作内的测试。如果c:when块中没有一个测试计算值为真的时候:如果出现c:otherwise动作内容时,则计算c:otherwise动作的内容:
<c:choose> <c:when test="${item.type == 'book'}"> ... </c:when> <c:when test="${item.type == 'electronics'}"> ... </c:when> <c:when test="${item.type == 'toy'}"> ... </c:when> <c:otherwise> ... </c:otherwise> </c:choose> |
c:foreach动作提供一个容易的方法来迭代一个集合的元素。如果你想只迭代集合的一部分的话,你可以分别用begin、 end、 和 step属性指定起点、终点和一个递增值。在下面的例子中,我们在变量customerNames中迭代一个集合的内容;在每个循环中,下一个元素输入到变量名内并在c:foreach动作的体内计算:
<table> <c:forEach var="name" items="${customerNames}"> <tr><td><c:out value="${name}"/></td></tr> </c:forEach> </table> |
记得Java的StringTokenizer类吗?有了c:forTokens动作,你可以用JSTL获得类似的功能。这个程序片断可使用在delims属性中定义的定界符通过items String属性中的条目迭代。注意,items 属性不必是一个字符直接量;它可以是任何有效的EL表达式:
<table> <c:forTokens items="47,52,53,55,46,22,16,2" delim="," var="dailyPrice"> <tr><td><c:out value="${dailyPrice}"/></td></tr> </c:forTokens> </table> |
在接下来的完整的JSTL页中,我列出了已经传递到该页的所有参数。param 和paramValues对象是映射关键字到一个或多个值的Java Map集。在本例中,我们找出了用于集合的每个MapEntry的关键字即参数名,并且使用关键字来查找所有与关键字关联的参数值:
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <html> <body> <head> <title>Parameter Listing Example</title> </head> <br> <b>Parameter values passed to this page for each parameter: </b> <table border="2"> <c:forEach var="current" items="${param}"> <tr> <td> <b><c:out value="${current.key}" /></b> </td> <c:forEach var="aVal" items="${paramValues[current.key]}"> <td> <c:out value="${aVal}" /> </td> </c:forEach> </tr> </c:forEach> </table> </body> </html> |
其他动作
我们也需要讨论一些其他重要的核心标记库动作。在网页实现中一个潜在的问题范围与URL编码有关。没有URL编码,在网页中传递的URL的某个字符如空格,可能会迷惑Web服务器。URL编码确保这些特殊的字符用不引起迷惑的字符代替。下列例子在变量myUrl中定义了一个URL,该变量myUrl由一个URL和一系列参数组成。URL动作(注意,这里只在JSTL意义上的动作)保证所有字符都正确的编码:
<c:url value="http://acme.com/exec/register" var="myUrl"> <c:param name="name" value="${param.name}"/> <c:param name="country" value="${param.country}"/> </c:url> <a href='<c:out value="${myUrl}"/>'>Register</a> |
在上面的代码中,param动作简单的定义了一组名值对。
JSP允许设计者用 <JSP:INCLUDE></JSP:INCLUDE> <jsp:include></jsp:include>
<jsp:include></jsp:include> <JSP:INCLUDE>指令包括其他页的内容。JSTL用JSTL c:import动作扩展了这个概念。c:import的主要优势是:你能指定一个任意的URL;也可以包含你的Web应用之外(W3C的任何地方)的页的内容或者你的服务器上的另一个Web应用内的页的内容。
对于一组与HTTP相关的标记来说,没有一个方法处理HTTP重定向是不完整的。JSTL用c:redirect动作支持它。
国际化标记库
在讨论了JSTL支持国际化中,我假设你已经有了对下列主题的合理的理解:
●资源包和Java如何找到它们
●Locale类
●资源包查找和MessageFormat类
●局部编码以及它与Java国际化的关系
●Java文本和数据格式化
如果你需要这些主题的更多的信息,请阅读Resources (http://www.javaworld.com/javaworld/jw-02-2003/jw-0228-jstl-p4.html#resources#resources)上的参考部分与国际化有关的参考文章。
我在下面的两个部分讨论了国际化标记库。在第一部分,我包括了你可能使用的格式化和解释相关的动作(它最初对应于java.text封装包中的类),尽管你没有开发过完全的国际化应用程序,可能你也要用到它。在第二部分,我说明了更针对于国际化的动作。
如果存在一个远程的可能性,你的应用程序会在你本国之外使用。如果你从一开始就建立在国际化的支持上,那么开发就会更加容易。无论你使用何种方法来开发,即使像JSTL一样容易使用的方法,一开始建立在国际化支持上也是十分有益的。
格式标记库:格式动作
如果你已经使用了Java的 DateFormat 和NumberFormat类,在下面的标记中使用的方法应该看起来眼熟,因为JSTL格式化动作是在这些类之上建立的。这些Java类普遍提供一个format( )函数,它将一个Java类型转化为一个格式化的String和创建对应于该String的Java对象。
fmt:formatNumber动作有一个value属性和一个pattern属性。value属性是一个与我们看到的其它value属性类似的EL表达式或者变量。pattern属性与在NumberFormat类中定义的模式一样。下列动作发送一个格式化的String到JSP页的输出上:
<fmt:formatNumber value="1000.001" pattern="#,#00.0#"/> |
在这个fmt:formatNumber动作里,我们使用了type属性来指定:格式化我们需要格式化的值为一个货币值。我们保存格式化的结果在一个变量名为dollars中。在一个美国的locale类中,下面的程序生成一个字符串$3456.79(注意,它将使用的货币值四舍五入了):
<fmt:formatNumber value="3456.789" type="currency" var="dollars"/> |
用于上面的type属性的可能值包括currency、 number、 和percent。
在例中,我们使用了另一种方法——使用了一个包括在value属性中的一个格式化的域(currency,每type属性)的一个文本字符串。并且解析它来获取一个数字。结果储存在由var属性指定的一个变量内。尽管这个属性是可选的,还是会经常使用它。另外,解析的值送到页输出上:
<fmt:parseNumber value="${currencyInput}" type="currency" var="parsedNumber"/> fmt:formatDate动作有一个value属性、一个format属性、 一个指向处理格式化的格式类的属性(典型的,如java.util.Date): <jsp:useBean id="now" class="java.util.Date" /> <fmt:formatDate value="${now}" timeStyle="long" dateStyle="long"/> |
像数字格式化一样,JSTL页提供一个机制来解析一个代表日期的、进入Date对象的字符串:
<fmt:parseDate value="${dateInput}" pattern="MM dd, YYYY" /> |
查看java.util.DateFormat类,了解如何处理格式化和模式的更多详细的资料。
格式标记库:国际化动作
Java本地化的一个关键点是ResourceBundle类。JSTL动作允许你用这个类简单的工作。这个例子使用了fmt:bundle动作来得到与当前Locale 和 fmt:message动作对应的一个ResourceBundle动作,从而查看该资源包中的本地化的字符串:
<fmt:bundle basename="myBundle"> <%-- Use values in myBundle --%> <fmt:message key="Introduction"> <fmt:param value="${loginName}"/> <fmt:param value="${loginCount}"/> </fmt:message> <fmt:formatDate value="${now}" var="parsedDate"/> </fmt:bundle> |
经常,fmt:message动作简单的查看了对应于一个关键词的字符串。在上面的例子中,在ResourceBundle中的字符串包含了取代两个值的占位符。这些值在fmt:param动作中定义过,这就像Java MessageFormat类使用的方法。
有一些类似的动作可指定一个时区,时区可应用到在标记的体中计算的任何事上:
<fmt:timeZone value="someTimeZone"> <!-- actions in this context will be evaluated using someTimeZone --> </fmt:timeZone> |
上述的fmt:bundle 和 fmt:timeZone动作有分别对应的fmt:setBundle和fmt:setTimeZone的动作。这些动作添加了可选的scope属性;因此,你可以使用这些动作在任何等同于应用范围的范围内设定一个资源捆绑或者一个时区。
如果你用非欧洲的locale类工作的话,你可能得担心编码的问题,JSTL支持用fmt:requestEncoding动作编码。
SQL标记库
JSTL 允许容易的数据库的集成。但是,值得注意的是:沙箱之外的JSTL的执行有一些限制。主要的问题与连接池有关。建立并维护到数据库的连接是很消耗资源的。JSTL SQL动作使得许多数据库连接建立起来,通常的,每个用户至少有一个。因此,JSTL SQL标记对于原型开发的或低容量的、基于Web的应用程序意义重大。但是它不适合于大规模的应用程序。一个可缩放的产品应用程序一般是在一个页面内处理数据库访问如隐藏数据库访问和处理像连接池之类的细节。但是,还是有方法允许你实现连接池和用一点自定义码来使用JSTL SQL动作(请看:"JSTL 1.0: What JSP Applications Need, Part 2" in Resources :http://www.javaworld.com/javaworld/jw-02-2003/jw-0228-jstl-p5.html#resources#resources).
我们看一些简单的例子。这些例子使用来自SQL库的JSTL标记。如果你熟悉SQL基础的话,你应该能够改编这些例子用在你的应用程序上。
在下面的程序片断中,我们建立了一条到一个数据库的连接,选择一组匹配一个订单ID的订单项目,并且在一个表格中显示item属性:
<sql:setDataSource driver="com.cheapDrivers.jdbcDriver" url="jdbc:cheapDrivers:." user="guest" password="password" var="dataSource" /> <sql:query var="orderItems" dataSource="${dataSource}"> SELECT * FROM items WHERE order_id = <cout value="${orderID}"/> ORDER BY price </sql:query> <table> <c:forEach var="row" items="${orderItems.rows}"> <tr> <td><c:out value="${row.itemName}"/></td> <td><c:out value="${row.price}"/></td> <td><c:out value="${row.weight}"/></td> </tr> </c:forEach> </table> |
在下一个例子中,我会说明JSTL是如何支持数据库事务的,在数据库中,许多包含对表格多个改动的操作必须是对所有的,或者什么也不做:如果出现一个问题时,改动必须为空操作。在下面例子中,sql:update动作包含在一个sql:transaction动作内,如果在事务处理过程中,存在任何SQL错误的话,在事务范围内执行的所有操作都得重来。
sql:update动作的命名有一点误导:除了SQL UPDATE外,sql:update也支持INSERT 和 DELETE,甚至是SQL CREATE。实际上,它支持不产生结果的任何一条SQL操作。在下面的例子中,sql:update通过插入变量值到一个PreparedStatement中来执行一个UPDATE动作。在这个代码片断中,我们在两个账户之间传送钱(需要预先包装在一个事务中的某些东西的一个经典的例子):
<sql:transaction dataSource="${dataSource}"> <sql:update> UPDATE account SET account_balance =account_balance -? WHERE accountNo = ? <sql:param value="${transferAmount}"/> <sql:param value="${sourceAccount}"/> </sql:update> <sql:update> UPDATE account SET account_balance =account_balance ? WHERE accountNo = ? <sql:param value="${transferAmount}"/> <sql:param value="${destAccount}"/> </sql:update> </sql:transaction> |
XML标记库
使用标准的XML标记库,你所能做的完整的处理,特别是可扩展性单一语言变换说明(XSLT)的处理,对于另一篇文章来说是一个很好的主题。下面我会涵盖足够的让你开始的知识。
在JSTL的XML支持遵循XPath规范。XPath的重要功能之一是为访问XML著名的分层的信息提供一个清晰的语法。也许看到每件是如何工作的最容易的方法就是看看我们如何使用来自于一个真实JSTL页的一个片断里的标记:
!-- Find and parse our XML document (somewhere on the WWW) --> <c:import url="http://www.cheapstuff.com/orderStatus?id=2435" var="xml"/> <x:parse xml="${xml}" var="doc"/> <!-- access XML data via XPath expressions --> <x:out select="$doc/name"/> <x:out select="$doc/shippingAddress"/> <x:out select="$doc/deliveryDate"/> <!-- Set a scoped variable --> <x:set var="custName" scope="request" select="$doc/name"/> |
在上面的输入和解析动作中,我们装载和解析了一个指定的XML文档到一个变量doc里。在上面的每个x:out动作中,我们使用了一个XPath表达式访问了解析的XML文档的元素,并且发送结果到JSP页输出中。
上面的设置表达式计算了一个XPath表达式并且将结果输入到一个限定范围的变量里(在上述例子中,它指在一个请求范围内)。
x:out 和x:set动作可以输出一个JspTagException。如果他们没有成功的话(极有可能因为XPath表达式指向并不存在的标记),你的页,像在所有其他情况下一样,应该智能的处理这些异常(要么通过传统的JSP errorPage指令,要么使用JSTL的c:catch动作),
JSTL容易处理XSLT转换。在下面的示范页中,我们使用来自XML标记库中的x:transform动作,用一个XSLT stylesheet创建一个来自于XML源文档的一个格式化的页。x:transform动作最重要的属性是XML和XSLT属性,在下面的例子中,我们设置了一个来自于我们在同一页初始化的变量的xslt属性;我们也在动作的体中设置了XML属性。该动作默认为x:transform动作。
默认的,转换的结果送到页输出上;你也可以保存结果到一个带x:var属性的变量内:
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x" %> <c:set var="xsltSource"> <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="music"> <html> <head></head> <body marginheight="0" marginwidth="0" topmargin="0" leftmargin="0"> <table cellpadding="0" cellspacing="0" border="1" bgcolor="#ffffff"> <tr> <td><STRONG>Artist</STRONG></td> <td><STRONG>Album</STRONG></td> <td><STRONG>Year</STRONG></td> <td><STRONG>Genre</STRONG></td> </tr> <!---Set up for loop to collect all the artist information //--> <!-- <xsl:for-each select="./*[name()='artists']"> --> <xsl:for-each select="artists"> <tr> <td><xsl:value-of select="artist"/></td> <td><xsl:value-of select="album"/></td> <td><xsl:value-of select="year"/></td> <td><xsl:value-of select="genre"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet> </c:set> <x:transform xslt="${xsltSource}" > <music> <artists> <artist>Jonny B</artist> <album>Feedback and Distortion</album> <year>2001</year> <genre>Rock</genre> </artists> <artists> <artist>Harmony's Nieces</artist> <album>Sappy Pop Ballads</album> <year>2002</year> <genre>Pop</genre> </artists> </music> </x:transform> |
你也能使用c:import动作再定义一个额外的源文档和stylesheet,就好像在这个示范的代码片断展示的一样::
<c:import var="${xmlSource}" url="${someDocumentURL}" /> <c:import var="${xsltSource}" url="${anotherDocumentURL}" /> <x:transform xml="${xmlSource}" xslt="${xsltSource}" > |
结束语
至此,你应该对JSTL、它的四种标准标记库、和它如何使网页开发更为容易 有了很好的理解。现在你开始写一些JSTL!
【关于作者】
Steve Small从事Java开发多年,一直处于技术领导层和开发位置上。他先后为Boeing、 Amazon.com工作过,目前在沃什湾西雅图的PictureIQ公司供职。从1998年起,在华盛顿大学兼职开发和教学Java课程。http://www.javaworld.com/feedback
你可以通过这个链接引用该篇文章:http://johnsonchen916.blogdriver.com/tb.b?diaryId=17212
发表评论
-
[软件人生]什么是程序员
2008-09-06 19:18 1137一个大专学历想做程序员的朋友和我的对话,很短,我觉得,至少能说 ... -
软件公司怎么消亡的?
2008-09-03 23:45 1075最近读了一篇非常有趣的文章,原文是英文,和大家共享,其大概意思 ... -
世上没有B/S系统,只有B系统和S系统. (转载)
2007-10-28 23:02 1154世上没有B/S系统,只有B ... -
从原则出发的软件开发(转载)
2007-06-24 18:57 1218原文:http://gocom.primeton.co ... -
关于java 的methode的内存区域问题
2007-06-12 14:49 1407用java这么长时间了,对于static method 大家都 ... -
java中静态方法和非静态方法覆盖的区别
2007-06-12 14:07 4784首先我们提供两个类,基类为Parent,派生类为Child。在 ... -
关于继承初始化的精典试题 (转载)
2007-06-07 15:50 1242一、 class First { void tt() { ... -
关于synchronized
2007-05-30 21:17 1155synchronized 关键字,它 ... -
关于Connection的问题
2007-05-29 09:48 1199最近在看Datasource时候想到,datasource是数 ... -
0碎的知识
2007-05-26 15:57 11521.软件设计模式针对的是代码片段的复用,而SOA实施中讨论的是 ... -
关于工厂模式和spring的IOC
2007-05-23 18:35 8017原文转之: http://gocom.primeton.com ... -
appfuse中/mainMenu.html的定向问题
2007-05-08 22:26 1579找了半天,终于找到了 : http://blog.matr ... -
Robbin推荐的java类书籍
2007-04-30 20:54 1352http://www.iteye.com/article/52 ... -
候捷谈Java反射机制
2007-04-08 14:19 1255Java反射机制<o:p></o:p> ... -
JDBC事务和JTA (XA)事务
2007-04-03 21:10 21917事务简介 一般情况下,J2EE应用服务器支持JDBC事务、 ... -
inline函数的用法小议(转载)
2007-03-14 15:22 8510inline函数的用法小议( ... -
关于java的JIT知识
2007-03-14 13:42 15967刚看Practical java ,对jit ... -
当前Java软件开发中几种认识误区
2007-03-12 21:07 1316当前Java软件开发中几种 ... -
在websphere上安装动态高速缓存监控器
2007-02-07 20:49 3649动态高速缓存的安装和配置 这一节探讨如何安装和配置动态高速缓存 ... -
SSL(Server Socket Layer)简介
2007-02-07 19:52 2187SSL(Server Socket Layer)简介 在网络 ...
相关推荐
少儿编程scratch项目源代码文件案例素材-和朋友们一起跳伞.zip
少儿编程scratch项目源代码文件案例素材-掉箱子.zip
少儿编程scratch项目源代码文件案例素材-格斗.zip
内容概要:本文详细介绍了三种主流的深度强化学习算法-DDPG、TD3和SAC在机器人控制领域的应用,特别是在MuJoCo仿真环境中的实现细节。首先解释了每个算法的基本原理及其独特之处,如DDPG的确定性策略生成器、TD3的双Critic网络以及SAC的熵最大化机制。接着深入探讨了这些算法的具体代码实现,包括Actor和Critic网络的设计、损失函数的构建以及一些实用的调参技巧。此外,还分享了许多实战经验和常见陷阱,如正确处理done信号、添加动作变化量惩罚项、观测空间的归一化等。 适合人群:对深度强化学习有一定了解并希望深入了解其在机器人控制领域应用的研究人员和技术爱好者。 使用场景及目标:帮助读者掌握如何将DDPG、TD3和SAC应用于具体的机器人控制任务中,提高算法性能,解决实际问题。同时,也为进一步研究提供了宝贵的实践经验。 其他说明:文中不仅提供了详细的理论讲解,还附带了大量的代码片段,便于读者理解和实践。对于想要深入理解这些算法内部运作机制的人来说,是一份不可多得的学习资料。
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 编译闪电般迅速,并发性能卓越,部署轻松简单!Go 语言以极简设计理念和出色工程性能,成为云原生时代的首选编程语言。从 Docker 到 Kubernetes,全球顶尖科技企业都在采用 Go。点击了解 Go 语言的核心优势、实战窍门和未来走向,开启高效编程的全新体验!
少儿编程scratch项目源代码文件案例素材-地图制作器.zip
【资源说明】 1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通。 2.主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 本文介绍了基于QEM(Quadric Error Metrics,二次误差度量)的优化网格简化算法的C和C++实现源码及其相关文档。这一算法主要应用于计算机图形学领域,用于优化三维模型的多边形数量,使之在保持原有模型特征的前提下实现简化。简化的目的是为了提高渲染速度,减少计算资源消耗,以及便于网络传输等。 本项目的核心是网格简化算法的实现,而QEM作为该算法的核心,是一种衡量简化误差的数学方法。通过计算每个顶点的二次误差矩阵来评估简化操作的误差,并以此来指导网格简化过程。QEM算法因其高效性和准确性在计算机图形学中广泛应用,尤其在实时渲染和三维打印领域。 项目代码包含C和C++两种语言版本,这意味着它可以在多种开发环境中运行,增加了其适用范围。对于计算机相关专业的学生、教师和行业从业者来说,这个项目提供了丰富的学习和实践机会。无论是作为学习编程的入门材料,还是作为深入研究计算机图形学的项目,该项目都具有实用价值。 此外,项目包含的论文文档为理解网格简化算法提供了理论基础。论文详细介绍了QEM算法的原理、实施步骤以及与其他算法的对比分析。这不仅有助于加深对算法的理解,也为那些希望将算法应用于自己研究领域的人员提供了参考资料。 资源说明文档强调了项目的稳定性和可靠性,并鼓励用户在使用过程中提出问题或建议,以便不断地优化和完善项目。文档还提醒用户注意查看,以获取使用该项目的所有必要信息。 项目的文件名称列表中包含了加水印的论文文档、资源说明文件和实际的项目代码目录,后者位于名为Mesh-Simplification-master的目录下。用户可以将这些资源用于多种教学和研究目的,包括课程设计、毕业设计、项目立项演示等。 这个项目是一个宝贵的资源,它不仅提供了一个成熟的技术实现,而且为进一步的研究和学习提供了坚实的基础。它鼓励用户探索和扩展,以期在计算机图形学领域中取得更深入的研究成果。
【资源说明】 1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通。 2.主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 本文介绍了基于QEM(Quadric Error Metrics,二次误差度量)的优化网格简化算法的C和C++实现源码及其相关文档。这一算法主要应用于计算机图形学领域,用于优化三维模型的多边形数量,使之在保持原有模型特征的前提下实现简化。简化的目的是为了提高渲染速度,减少计算资源消耗,以及便于网络传输等。 本项目的核心是网格简化算法的实现,而QEM作为该算法的核心,是一种衡量简化误差的数学方法。通过计算每个顶点的二次误差矩阵来评估简化操作的误差,并以此来指导网格简化过程。QEM算法因其高效性和准确性在计算机图形学中广泛应用,尤其在实时渲染和三维打印领域。 项目代码包含C和C++两种语言版本,这意味着它可以在多种开发环境中运行,增加了其适用范围。对于计算机相关专业的学生、教师和行业从业者来说,这个项目提供了丰富的学习和实践机会。无论是作为学习编程的入门材料,还是作为深入研究计算机图形学的项目,该项目都具有实用价值。 此外,项目包含的论文文档为理解网格简化算法提供了理论基础。论文详细介绍了QEM算法的原理、实施步骤以及与其他算法的对比分析。这不仅有助于加深对算法的理解,也为那些希望将算法应用于自己研究领域的人员提供了参考资料。 资源说明文档强调了项目的稳定性和可靠性,并鼓励用户在使用过程中提出问题或建议,以便不断地优化和完善项目。文档还提醒用户注意查看,以获取使用该项目的所有必要信息。 项目的文件名称列表中包含了加水印的论文文档、资源说明文件和实际的项目代码目录,后者位于名为Mesh-Simplification-master的目录下。用户可以将这些资源用于多种教学和研究目的,包括课程设计、毕业设计、项目立项演示等。 这个项目是一个宝贵的资源,它不仅提供了一个成熟的技术实现,而且为进一步的研究和学习提供了坚实的基础。它鼓励用户探索和扩展,以期在计算机图形学领域中取得更深入的研究成果。
少儿编程scratch项目源代码文件案例素材-鸽子飞行模拟器.zip
少儿编程scratch项目源代码文件案例素材-仿作马里奥冒险.zip
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 编译闪电般迅速,并发性能卓越,部署轻松简单!Go 语言以极简设计理念和出色工程性能,成为云原生时代的首选编程语言。从 Docker 到 Kubernetes,全球顶尖科技企业都在采用 Go。点击了解 Go 语言的核心优势、实战窍门和未来走向,开启高效编程的全新体验!
内容概要:本文详细介绍了如何利用Carsim和Simulink进行线控转向系统的联合仿真。首先解释了线控转向系统的基本概念及其重要性,特别是在自动驾驶领域的应用前景。接着阐述了Carsim和Simulink的集成方法,包括环境配置、模型对接、S函数接口的具体实现步骤以及注意事项。文中还提供了转向控制算法的实例,如PID控制器的设计思路和参数选择依据,并强调了数据同步的重要性,分享了一些实用的小技巧,如通过XY Graph监测转向性能、确保仿真步长的一致性等。最后指出,这套仿真平台非常适合用于验证各种高级驾驶辅助系统的控制算法,能够显著提高开发效率并降低成本。 适合人群:汽车电子工程师、自动驾驶研究人员、控制系统开发者。 使用场景及目标:适用于需要快速迭代和验证线控转向及相关自动驾驶控制算法的研发阶段,帮助工程师们在虚拟环境中完成大量实验,减少实物测试的风险和成本。 其他说明:文中提到的技术细节对于理解和实施线控转向系统的联合仿真非常关键,尤其是关于数据同步和控制算法优化的部分。此外,作者还分享了许多个人经验教训,有助于避免常见的错误和技术陷阱。
内容概要:本文详细介绍了如何使用LabVIEW与ABB设备进行集成,主要涉及通过OPC UA协议获取ABB设备的日志、设备信息、速度及状态等关键数据。文中提供了具体的LabVIEW代码示例,涵盖了通信配置、数据解析、状态监测、日志抓取等多个方面。此外,还分享了许多实际操作中的经验和技巧,如TCP/IP通信、JSON数据处理、错误处理机制以及数据可视化的最佳实践。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些熟悉LabVIEW并希望深入了解ABB设备集成的人群。 使用场景及目标:适用于需要对ABB设备进行实时监控和数据分析的工程项目。具体目标包括:① 实现与ABB设备的高效通信;② 获取并解析设备的关键数据;③ 监控设备状态并记录日志;④ 提升系统的可靠性和稳定性。 其他说明:本文不仅提供理论指导,还结合了大量的实战案例和代码片段,帮助读者更好地理解和应用相关技术。
毕业设计-基于JavaSE实现魂动罗小游戏 1. Demo简介 本demo仿制了一个魂斗罗小游戏,纯JavaSE实现。 [image] 1.1 技术应用 ● 键盘控制 ● 图片显示 ● 音频播放 ● 多线程控制 2. demo使用 拿到源码后进入MainFrame主类中运行: public static void main(String[] args) { new Thread(new MainFrame()).start(); } [image] 按照右侧使用说明控制,无限生命。 3. 总结 简单的JavaSE小demo,需要练手的同学拿去看看。 [image]
内容概要:本文详细介绍了如何使用西门子PLC(如S7-1200/1500)通过Modbus协议与第三方仪表进行数据读写。主要内容涵盖硬件接线、Modbus库函数的正确使用、常见错误及其解决方法、性能优化技巧以及调试建议。文中强调了地址转换、字节顺序、超时设置等方面的具体操作和注意事项,并提供了多个代码示例来帮助理解和实施。 适合人群:从事工业自动化领域的工程师和技术人员,特别是那些需要将西门子PLC与其他品牌仪表集成在一起工作的专业人士。 使用场景及目标:适用于需要在工业环境中实现PLC与各种传感器、变送器和其他智能设备之间的可靠通信的场合。目标是确保数据传输的准确性、稳定性和效率,减少调试时间和成本。 其他说明:作者分享了许多基于实际项目的宝贵经验教训,提醒读者注意一些容易忽视但可能导致严重问题的小细节。此外,还提供了一些实用工具和方法用于辅助开发和维护工作。
内容概要:本文详细介绍了使用MATLAB模拟8DPSK(八进制差分相移键控)信号在AWGN(加性白高斯噪声)信道下的误码率(BER)和误比特率(SER)性能。文中通过具体代码展示了从生成随机二进制序列、调制、加入噪声、解调到最后计算误码率的完整流程,并将仿真结果与理论值进行了对比。同时,文章还讨论了一些常见的陷阱和技术要点,如相位偏移、格雷编码的应用以及信噪比(Eb/N0)的正确转换方法。 适合人群:具有一定MATLAB编程基础和数字通信基础知识的研究人员、工程师和学生。 使用场景及目标:适用于希望深入了解8DPSK调制特性及其在AWGN信道中性能的人群。通过本实验,读者能够掌握8DPSK的基本原理、MATLAB仿真技巧以及误码率分析的方法。 其他说明:文章提供了详细的代码片段和解释,帮助读者更好地理解和复现实验结果。此外,还提到了一些提高仿真实验效率的小技巧,如使用并行计算加速仿真过程。
少儿编程scratch项目源代码文件案例素材-赌注和梯子.zip
内容概要:本文详细介绍了如何利用信捷XD5控制器和威纶触摸屏编写高效的六轴机械手控制程序。主要内容涵盖系统概述、程序编写步骤、代码分析、实际应用效果等方面。文中强调了系统的初始化、通信参数配置、运动控制、调试日志输出等关键功能模块的设计思路和技术要点。此外,还展示了程序的实际应用案例及其优势,如高可靠性、操作便捷性和良好的扩展性。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对六轴机械手控制系统感兴趣的读者。 使用场景及目标:①掌握信捷XD5控制器和威纶触摸屏的联合使用方法;②理解六轴机械手控制程序的编写流程和关键技术;③提高六轴机械手在实际生产中的稳定性和效率。 其他说明:本文不仅提供了详细的代码示例和注释,还分享了许多实际应用中的经验和技巧,有助于读者更好地理解和应用相关技术。
内容概要:本文详细介绍了C#工业自动化通信开发库的强大功能及其应用。该库提供了丰富的通信类型,包括串口通信、TCP/IP、UDP、CAN总线、Profinet、Modbus、PLC通信、OPC UA/DA、HTTP、数据库操作、INI文件操作、Excel表格操作、RabbitMQ消息队列管理和常用数据转换等功能。此外,库还在持续更新,增加了诸如高并发物联网接收服务器端、DTU服务器、EF6+多类型数据库支持、OPC DA的DCOM组件封装等新特性。文中通过具体代码示例展示了各个功能的实际使用方法,并强调了库在工业自动化领域的实用性。 适合人群:从事工业自动化软件开发的技术人员,尤其是熟悉C#编程语言的开发者。 使用场景及目标:适用于需要处理多种工业设备通信协议和数据库操作的项目。主要目标是提高开发效率,减少重复劳动,确保通信和数据处理的可靠性。 其他说明:该库不仅提供了丰富的功能,而且在性能优化、错误处理等方面也有出色表现。例如,自动处理CRC校验、智能重连机制、环形缓冲区设计等特性使得开发更加便捷和稳定。
内容概要:本文详细介绍了FX3U与三菱伺服控制框架的标准程序及其应用,特别针对新手提供了全面的入门指南。主要内容涵盖公共参数设定、回原点操作、JOG手动模式、绝对定位和相对定位的具体实现方式,并附有详细的代码示例。同时,文章还深入讲解了伺服驱动器的针脚接线方法,确保硬件连接无误。通过这些内容,新手能够系统地理解和掌握定位控制的基本原理和技术要点。 适合人群:初学者和有一定经验的自动化控制工程师,尤其是希望深入了解FX3U与三菱伺服控制系统的人员。 使用场景及目标:适用于工业自动化领域的定位控制系统开发和维护。主要目标是帮助读者快速上手并熟练掌握FX3U与三菱伺服控制的技术细节,提高工作效率和系统稳定性。 其他说明:文中不仅提供理论知识,还有大量实用的操作技巧和注意事项,如参数设置的最佳实践、常见错误避免等,有助于读者在实际项目中少走弯路。