SP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。

JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。

根据JSTL标签所提供的功能,可以将其分为5个类别。

  • 核心标签
  • 格式化标签
  • SQL 标签
  • XML 标签
  • JSTL 函数


JSTL 库安装

Apache Tomcat安装JSTL 库步骤如下:

  • 从Apache的标准标签库中下载的二进包(jakarta-taglibs-standard-current.zip)。下载地址:​​http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/​
  • 下载jakarta-taglibs-standard-1.1.1.zip 包并解压,将jakarta-taglibs-standard-1.1.1/lib/下的两个jar文件:standard.jar和jstl.jar文件拷贝到/WEB-INF/lib/下。

使用任何库,你必须在每个JSP文件中的头部包含<taglib>标签。

 

使用标签时,一定要在jsp文件头加入以下代码:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"


为什么使用taglib?

所谓 标记库(tag library),是指由在JSP页面中使用的标记所组成的库。JSP容器推出时带有一个小型的、默认的标记库。而 自定义标记库是人们为了某种特定的用途或者目的,将一些标记放到一起而形成的一种库。在一个团队中协同工作的开发者们可能会为各自的项目创建一些非常特定化的自定义标记库,同时也会创建一个通用自定义标记库,以供当前使用。

JSP 标记替代了scriptlet,并缓解了由scriptlet所招致的所有令人头痛的事情。例如,您可以看到这样的标记:



<store:shoppingCart id="1097629"/>


或者这样的标记:



<tools:usageGraph />


每个标记都包含了指向一个Java类的引用,但是类中的代码仍然在它该在的地方:在标签之外,一个编译好的类文件之中。

 

从 scriptlet 到标记

创建一个自定义标记的第一步就是决定您想怎样使用它,如何称呼它,以及它允许使用或者需要什么属性(如果有的话)。对于时间戳标记,我们所需要的很简单:只要一个能够输出一个页面的最后修改数据的简单标记。

因为不需要属性,这个标记看上去就是这个样子:



<site-utils:lastModified />


这个标记的名称和前缀是一样的:都是 ​​site-utils​​ 。元素的内容是空的,这意味着该元素中不允许有子元素存在。定义了这个标记之后,接下来的一步就是实现它的行为。

实现行为

实现标记行为的第一步是将scriptlet代码从原先所在的地方移到一个Java类( ​​LastModifiedTag​​ )中,如清单 1 所示:

清单 1. 创建一个时间戳标记



package com.newInstance.site.tags;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.tagext.TagSupport;
public class LastModifiedTag extends TagSupport {
public int doEndTag() {
try {
HttpServletRequest request =
(HttpServletRequest)pageContext.getRequest();
String path = pageContext.getServletContext().getRealPath(
request.getServletPath());
File file = new File(path);
DateFormat formatter = DateFormat.getDateInstance(
DateFormat.LONG);
pageContext.getOut().println(
formatter.format(new Date(file.lastModified())));
} catch (IOException ignored) { }
return EVAL_PAGE;
}
}


这个方法中的代码看上去比较熟悉;实质上,它正是我们在先前用到的相同的时间戳代码。由于不需要用户输入,而且该标记也没有属性或者嵌入的内容,我们惟一需要关心的一个新方法就是 ​​doEndTag()​​ (),在这个方法中该标记可以输出内容(在这个例子中是最后修改数据)到JSP页面。

清单 1 中其他的更改更多地与作为一个JSP标记的代码有关,而与在一个页面内运行的scriptlet没有多大关系。例如,所有的JSP标记都应该扩展JSP类 ​​javax.servlet.jsp.tagext.TagSupport​​ ,这个类为JSP标记提供了基本框架。可能您还注意到 ,该标记返回的 ​​EVAL_PAGE​​ .​​EVAL_PAGE​​ 是一个预定义的整型常量,它指示容器处理页面的剩下部分。另一种选项就是使用 ​​SKIP_PAGE​​ ,它将中止对页面剩下部分的处理。如果您要将控制转移到另一个页面,例如您要前进(forward)或者重定向(redirect)用户,那么只需要使用 ​​SKIP_PAGE​​ 。剩下来的细节都是与时间戳自身有关的事情。

接下来,编译这个类,并将 LastModifiedTag.class 文件放到一个WEB-INF/classes 目录下,注意要放到正确的路径层次结构中。这个路径应该匹配该标记的包名,包名中的圆点(.)用斜杠(/)代替。在本例中,目录的路径是基路径(WEB-INF/classes)再加上层次结构com/newInstance/site/tags。如果有一个名为 ​​foo.bar.tag.MyTag​​ 的标记,那么它将被放在 WEB-INF/classes/foo/bar/tag中。这种路径层次结构确保了Web容器在任何需要装载该标记的时候都能够找到这个类。

创建TLD

接下来的一步是创建一个 标记库描述符(tag library descriptor ,TLD)文件。TLD向容器和任何要使用该标记库的JSP页面描述您的标记库。清单 2 显示了一个非常标准的TLD,其中只包含了一个标记。当您将更多的标记添加到库中时,TLD文件的长度和复杂性将随之增长。

清单 2. 一个标记库描述符



<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2/EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>site-utils</short-name>
<uri>http://www.newInstance.com/taglibs/site-utils</uri>
<tag>
<name>lastModified</name>
<tag-class>com.newInstance.site.tags.LastModifiedTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>


TLD 文件顶部的信息应用于整个标记库。在本例中,我提供了一个版本(这对于跟踪某个标记库的JSP创建者拥有哪个版本很有用,尤其是在您需要经常修改标记库的情况下更是如此);该标记库所依赖的JSP版本;一个为该标记库推荐的前缀;以及用于引用这个标记库的URI。注意,我使用了前缀 ​​short-name​​ 作为URI的一部分,这样 比较容易将前缀和标记库的URI看成一个整体。

剩下的信息用于一个特定的标记,这些信息用 ​​tag​​ 元素表示。我指定了该标记的名称、用于该标记的类(这个类应该被编译好并放在适当的地方,以便容器能够装载),最后还指定了该标记是否有嵌入的内容。在本例中,标记没有嵌入的内容,因此使用"empty"。

保存这个文件,并将其放到WEB-INF/tlds目录下(您可能需要在您的容器中创建这个目录)。我将这个文件保存为site-utils.tld,并在该标记库的URI(推荐的前缀)和TLD文件本身之间再次创建一个干净的链接。对于这个特定的标记库,要使其可以使用,最后一步要做的是让您的Web应用知道如何连接一个JSP页面中的URI,如何请求使用一个标记库。这可以通过应用的web.xml文件来做。清单 3 显示了一个非常简单的web.xml片段,正是 它为我们的标记库做这样的事情。

清单 3. 将一个URI与一个标记库链接起来



<taglib>
<taglib-uri>http://www.newInstance.com/taglibs/site-utils</taglib-uri>
<taglib-location>/WEB-INF/tlds/site-utils.tld</taglib-location>
</taglib>


 

包装起来

如果您已经按照上述步骤执行了,那么现在您应该能够在JSP页面中引用新标记了。清单 4 向我们展示了新改进的footer.jsp,这个文件中现在完全没有scriptlet,也没有指向具有scriptlet的JSP页面的引用。

清单 4. 使用新的标记库



<%@ taglib prefix="site-utils"
uri="http://www.newInstance.com/taglibs/site-utils" %>
</td>
<td width="16" align="left" valign="top"> </td>
</tr>
<!-- End main content -->
<!-- Begin footer section -->
<tr>
<td width="91" align="left" valign="top" bgcolor="#330066"> </td>
<td align="left" valign="top"> </td>
<td class="footer" align="left" valign="top"><div align="center"><br>
&copy; 2003
<a href="mailto:webmaster@newInstance.com">Brett McLaughlin</a><br>
Last Updated: <site-utils:lastModified />
</div></td>
<td align="left" valign="top"> </td>
<td width="141" align="right" valign="top" bgcolor="#330066"> </td>
</tr>
</table>
<!-- End footer section -->


在前面几期中看了JSTL如何工作(参见“ ​​利用JSTL更新您的JSP页面​​”和“ ​​导入内容到您的Web站点​​”)之后,接下来该做什么您应该很清楚了:我们通过使用web.xml文件中的URI来引用这个标记库,为之分配一个前缀(来自TLD的 ​​short-name​​ 始终是最好的选择),然后就像使用任何其他JSP标记一样使用这个标记。最终得到的是一个简洁的、更好的JSP页面,这个JSP页面运行起来不比有 scriptlet 的时候差。

http://www.ibm.com/developerworks/cn/java/j-jsp07233/


​<c:forEach>详解​



<c:forEach>标签的语法定义如下所示。


                    <c:forEach var="name" items="expression" varStatus="name" 


                             begin="expression" end="expression" step="expression">


                             body content 


                    </c:forEach>


           <c:forEach>标签具有以下一些属性:


l            var:迭代参数的名称。在迭代体中可以使用的变量的名称,用来表示每一个迭代变量。类型为String。


l            items:要进行迭代的集合。对于它所支持的类型将在下面进行讲解。


l            varStatus:迭代变量的名称,用来表示迭代的状态,可以访问到迭代自身的信息。


l            begin:如果指定了items,那么迭代就从items[begin]开始进行迭代;如果没有指定items,那么就从begin开始迭代。它的类型为整数。


l            end:如果指定了items,那么就在items[end]结束迭代;如果没有指定items,那么就在end结束迭代。它的类型也为整数。


l            step:迭代的步长。


           <c:forEach>标签的items属性支持Java平台所提供的所有标准集合类型。此外,您可以使用该操作来迭代数组(包括基本类型数组)中的元素。它所支持的集合类型以及迭代的元素如下所示:


l            java.util.Collection:调用iterator()来获得的元素。


l            java.util.Map:通过java.util.Map.Entry所获得的实例。


l            java.util.Iterator:迭代器元素。


l            java.util.Enumeration:枚举元素。


l            Object实例数组:数组元素。


l            基本类型值数组:经过包装的数组元素。


l            用逗号定界的String:分割后的子字符串。


l            javax.servlet.jsp.jstl.sql.Result:SQL查询所获得的行。


           不论是对整数还是对集合进行迭代,<c:forEach>的varStatus属性所起的作用相同。和var属性一样,varStatus用于创建限定了作用域的变量(改变量只在当前标签体内起作用)。不过,由varStatus属性命名的变量并不存储当前索引值或当前元素,而是赋予javax.servlet.jsp.jstl.core.LoopTagStatus类的实例。该类包含了一系列的特性,它们描述了迭代的当前状态,如下这些属性的含义如下所示:


l            current:当前这次迭代的(集合中的)项。


l            index:当前这次迭代从0开始的迭代索引。


l            count:当前这次迭代从1开始的迭代计数。


l            first:用来表明当前这轮迭代是否为第一次迭代,该属性为boolean类型。


l            last:用来表明当前这轮迭代是否为最后一次迭代,该属性为boolean类型。


l            begin:begin属性的值。


l            end:end属性的值


l            step:step属性的值


下面就来看一个个基本的例子,表格隔行背景色变化

<c:forEach var="item" items="${contents}" varStatus="status">

            <tr <c:if test="${status.count%2==0}">bgcolor="#CCCCFE"</c:if> align="left">

            xxx            </tr>

</c:forEach>


<c:forEach var="给你list起的别名" items="${adminList}"> 

${给你list起的别名.Admin的属性} 

</c:forEach>


 


foreach序号:


<c:forEach items="${signBusList}" var="sign" varStatus="xh"> 


       ${xh.count}序号从1开始 


      ${xh.index}序号从0开始 


      ${xh.last}最后一个序号 


     ${xh.first}第一个序号 


</cforEach> 


 


 


 


​实现if elseif else的jsp标签。​



. jsp中的类似  if - else 语句 的语法

<c:choose>

   <c:when test="${requestScope.newFlag== '1' || requestScope.newFlag== '2' ||requestScope.newFlag== '3'}">  

         作品名称: ${star.class_}<br />

         作品编号: ${star.raceNum}<br />       

   </c:when>

   <c:otherwise> 

     班级: ${star.class_}<br />

     参赛编号: ${star.raceNum}<br /> 

   </c:otherwise>

</c:choose>

 

 

 


数字相除:



  1. c:set var="intVar1" value="6" />  
  2. <c:set var="intVar2" value="4" />  
  3. <c:set var="intVar3" value="${intVar1/intVar2}" /> //1.5  
  4. <fmt:parseNumber var="intVar4" integerOnly="true" value="${intVar1/intVar2}" /> //1  

格式化日期

< fmt:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss"/>

 

​el表达式保留两位小数、使用jstl <fmt:formatNumber>标签保留两位小数​

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<fmt:formatNumber type="number" value="${688.87 * 0.8 }" pattern="0.00" maxFractionDigits="2"/>



上面代码输出结果为:551.10

 

  1. 从后台传入的值是deltmain。 这里的pattern就相当于DecimalFormat。  
  2. <fmt:formatNumber value="${deltmain}" pattern="##.##" minFractionDigits="2" ></fmt:formatNumber>  

 

JSTL在页面输出某个map的key值。

jstl的迭代取值

     当forEach 的items属性中的表达式的值是java.util.Map时,则var中命名的变量的类型就是 java.util.Map.Entry。这时var=entry的话,用表达式${entry.key}取得键名。 


  用表达式${entry.value}得到每个entry的值。这是因为java.util.Map.Entry对象有getKey和getValue方法,表达式语言遵守JavaBean的命名约定




Java代码  ​JSTL 核心标签库_java


  1. <c:forEach items="${map}" var="entry">    
  2.    <c:out value="${entry.key}" />    
  3.    <c:out value="${entry.value}" />    
  4. </c:forEach>   


 3、jstl根据key取值

 

一、如果知道key值,${map.key1}

二、如果key值是个变量, 则${map.[key]}, 使用数组访问方式,同样也可以用在知道key   ${map.["key1"]}

三、map


2、根据key变量求值 

      如果事先知道key那么很容易根据${map.key值}就可以得到值对象,但是如果key是一个变量呢? 


     有一个问题,如果给定一个key的变量如何使用EL得到对象呢,这里需要使用EL表达式中的[]来解决, 

    解决方法如示例: 



Java代码  ​JSTL 核心标签库_jsp页面_02


  1. <c:out value="${map[key]}" />  

  

<!-- 这里的map就是 java.util.Map对像,key是这个map里的一个key --> 

 


​<​​​​c:set​​ ​​var​​​​=​​​​"aPeriod"​​ ​​value​​​​=​​​​"${selectYear*100+selectMonth}"​​ ​​/>​


​${historyMap[aPeriod]}​


 


 


 



jstl获取字符串长度并截取

jstl1.1引入了一个fn.tld的标签,用于处理字符,如获得字符length,substring,indexof,endWith,lowcase 

实现截取字符串 

如: 

<c:set var="log.logTitle" value="做一个截取字符串长度的测试" 

<c:choose> 

    <c:when test="${fn:length(log.logTitle) > 10}"> 

     <c:out value="${fn:substring(log.logTitle, 0, 10)}......" /> 

    </c:when> 

    <c:otherwise> 

     <c:out value="${log.logTitle}" /> 

    </c:otherwise> 

   </c:choose> 

 

split 

把字符串按照指定字符切分 

${fn:split(customerNames, ";")} 

 

 


<c:forEach>标签的语法定义如下所示。


                    <c:forEach var="name" items="expression" varStatus="name" 


                             begin="expression" end="expression" step="expression">


                             body content 


                    </c:forEach>


           <c:forEach>标签具有以下一些属性:


l            var:迭代参数的名称。在迭代体中可以使用的变量的名称,用来表示每一个迭代变量。类型为String。


l            items:要进行迭代的集合。对于它所支持的类型将在下面进行讲解。


l            varStatus:迭代变量的名称,用来表示迭代的状态,可以访问到迭代自身的信息。


l            begin:如果指定了items,那么迭代就从items[begin]开始进行迭代;如果没有指定items,那么就从begin开始迭代。它的类型为整数。


l            end:如果指定了items,那么就在items[end]结束迭代;如果没有指定items,那么就在end结束迭代。它的类型也为整数。


l            step:迭代的步长。


           <c:forEach>标签的items属性支持Java平台所提供的所有标准集合类型。此外,您可以使用该操作来迭代数组(包括基本类型数组)中的元素。它所支持的集合类型以及迭代的元素如下所示:


l            java.util.Collection:调用iterator()来获得的元素。


l            java.util.Map:通过java.util.Map.Entry所获得的实例。


l            java.util.Iterator:迭代器元素。


l            java.util.Enumeration:枚举元素。


l            Object实例数组:数组元素。


l            基本类型值数组:经过包装的数组元素。


l            用逗号定界的String:分割后的子字符串。


l            javax.servlet.jsp.jstl.sql.Result:SQL查询所获得的行。


           不论是对整数还是对集合进行迭代,<c:forEach>的varStatus属性所起的作用相同。和var属性一样,varStatus用于创建限定了作用域的变量(改变量只在当前标签体内起作用)。不过,由varStatus属性命名的变量并不存储当前索引值或当前元素,而是赋予javax.servlet.jsp.jstl.core.LoopTagStatus类的实例。该类包含了一系列的特性,它们描述了迭代的当前状态,如下这些属性的含义如下所示:


l            current:当前这次迭代的(集合中的)项。


l            index:当前这次迭代从0开始的迭代索引。


l            count:当前这次迭代从1开始的迭代计数。


l            first:用来表明当前这轮迭代是否为第一次迭代,该属性为boolean类型。


l            last:用来表明当前这轮迭代是否为最后一次迭代,该属性为boolean类型。


l            begin:begin属性的值。


l            end:end属性的值


l            step:step属性的值


下面就来看一个个基本的例子,表格隔行背景色变化

<c:forEach var="item" items="${contents}" varStatus="status">

            <tr <c:if test="${status.count%2==0}">bgcolor="#CCCCFE"</c:if> align="left">

            xxx            </tr>

</c:forEach>