第5章〓JSTL标签库 JSTL(Jakarta Server Pages Standard Tag Library)是JSP标准标签库的简称。 在早期的JSP开发中,JSP与Servlet的职责定位模糊,开发人员习惯上在JSP中做很多的逻辑工作,HTML代码与Java代码混杂,逻辑功能、控制功能、视图功能都混淆在了一起。这种开发模式给代码的开发、阅读、维护都带来很大的麻烦。 随着MVC架构的出现,Jakarta EE中增加了JSTL标准。JSTL的目标是提供给Jakarta Web开发人员一个标准的、通用的标签库,开发人员可以利用这些标签取代JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护难度。 JSTL在本质上是提前定义好的一组标签,这些标签封装了不同的功能,在页面上调用JSTL,可以大幅减少JSP文件中的Java代码。这使Java代码与HTML代码明显分离,因此使用JSTL标签库更符合MVC设计理念。使用JSTL后,JSP可以专注于视图功能,为Jakarta Web开发带来非常大的好处。 Eclipse集成Tomcat进行Jakarta Web开发时,需要单独导入JSTL相关包。下载jstlimpl3.0.jar和jstlapi3.0.jar,复制到WEBINF/lib文件夹下即可使用JSTL。 JSTL 3.0包含的标签库内容见表51。 表51JSTL 3.0包含的标签库内容 功能URI前缀 核心库jakarta.tags.corec XML处理jakarta.tags.xmlx I18N格式化jakarta.tags.fmtfmt 关系型数据库访问SQLjakarta.tags.sqlsql 函数jakarta.tags.functionsfn 注意,Jakarta EE 10中包含的JSTL是3.0版。Jakarta EE 10对应的JSP版本是3.1。JSTL 3.0需要JSP 3.1及以上的Web容器支持。EL表达式是JSP规范的一部分,在JSTL操作中会大量使用EL,而EL是从JSP 2.0规范开始的。 本章只着重介绍几个常用标签的使用,其他内容参见Jakarta JSTL规范。 视频讲解 5.1自定义标签库 标签库由标签库描述文件tld(taglibrary descriptors)和标签实现类两部分组成。JSTL标签库中的所有标签与自定义标签定义方法相同。下面自定义一个作者标签,显示作者的名字和性别,通过这个案例了解JSTL标签库的定义过程。 (1) 定义标签类。 新建Web项目ETCTag,创建包com.icss.tag,定义标签类AuthorTag继承Jakarta.servlet.jsp.tagext.TagSupport。一般会重写doEndTag()方法。 public class AuthorTag extends TagSupport{ private String name; private String sex; public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int doEndTag() throws JspException { JspWriter out = pageContext.getOut(); try{ out.println(""); out.println(""); if(sex != null) out.println(""); else out.println(""); out.println(""); out.println("
作者:" + name + ",性别: " + sex + ",welcome you!!! 作者:" + name + ",welcome you!!!
"); }catch(Exception ex){ ex.printStackTrace(); } return this.EVAL_PAGE; } } (2) 定义标签库描述文件etc.tld。 的子元素为标签库前缀。一个下可以定义多个标签。 标签的子元素为标签名,为标签实现类,为标签的属性。 属性的子元素是属性名,表示属性是否为必须设置,false表示可选,true表示必须设置值; 表示是否可以动态赋值,false表示只能设置静态值,true表示可以动态赋值,如可以使用Java表达式、EL表达式或赋值。 etc our library etc library 3.0 etc http://com.icss.tag/core show file author author com.icss.tag.AuthorTag JSP author name name true true author sex sex false true (3) 在JSP项目TagUse中调用自定义标签。 把AuthorTag编译成lib文件,导入JSP项目中。 把etc.tld复制到JSP项目的WEBINF下。 在JSP文件中调用自定义标签。 <%@ page language="java" import="java.util.*" pageEncoding="GBK"%> <%@ taglib uri="http://com.icss.tag/core" prefix="etc"%> This is author tag use sample page.

5.2核心标签库 核心标签库前缀统一使用标识,这个标签库作用最大、用途最广。 参见jstlimpl3.0.jar/METAINF/c.tld中核心标签描述: JSTL core library JSTL core 3.0 c jakarta.tags.core 使用标签库时,需要在JSP页面的头部用taglib指令声明,表示标签前缀,在标签声明时需要指明。 <%@ taglib prefix="c" uri="jakarta.tags.core"%> 5.2.1一般用途标签 视频讲解 本节介绍几个一般用途的常用标签,分别为标签不常用,本节不作介绍。 1. 标签与<%=脚本表达式 %> 或 ${el表达式}的功能基本一致,用于在页面输出静态或动态信息。 基本语法如下,属性信息见表52。 表52属性信息 属性名动态支持属性类型描述 valuetrueObject要输出的表达式值 escapeXmltrueBoolean决定字符<,>、&、’,”在结果串中是否需要转义成对应的字符实体代码,默认为true。HTML转义符见表14 defaulttrueObject输出结果为null时,显示默认值 示例51

你有 个选项

示例52 当EL表达式输出为null时,可以使用输出默认值。 所属城市: 2. 基本语法如下,属性信息见表53。 表53属性信息 属性名动 态 支 持属 性 类 型描述 valuetrueObject要设置的表达式值 vartrueString存储在域对象中的变量名 scopefalseString与var对应的域对象 示例53 使用Java脚本计算一个随机数,然后用标签把随机数存储到request域对象中,最后用EL表达式提取request对象中的变量r,用输出随机数。 <% int rand = (int)(Math.random()*100); %> 获取随机数: 3. 基本语法如下,属性信息见表54。 表54属性信息 属性名动 态 支 持属 性 类 型描述 varfalseString存储在域对象中的变量名 scopefalseString与var对应的域对象 示例54 使用移除request域中存储的随机数rand。 <% int rand = (int)(Math.random()*100); request.setAttribute("rand", rand); %> 获取随机数:
移除后随机数: 5.2.2条件判断标签 视频讲解 Java脚本中,条件判断语句有if…else、if…else if…else if…else等。JSTL的目的是简化Java脚本,因此条件判断标签必不可少。 示例55 This is your first visit. Welcome to the site! 1. 条件判断标签,如果测试条件为true,显示标签体内容。标签定义如下: if org.apache.taglibs.standard.tag.rt.core.IfTag JSP test true true boolean var false false scope false false 基本语法如下,属性信息见表55,test为必选属性,var和scope为可选属性。 内容体 表55属性信息 属性名动 态 支 持属 性 类 型描述 testtrueBoolean测试条件返回为真,处理内容体信息,否则不处理 varfalseString把测试条件返回的布尔值结果,存储到scope对象中 scopefalseStringpage、request、session、application中的某个域对象 示例56 JSTL与EL标签配合使用,判断图书价格是否小于或等于100(符合预算),如是,则显示图书名称。 The book ${book.title} fits your budget! 示例57 测试请求参数中是否有一个名字为name的参数,如果参数为空,则提示。 Please specify your name. 示例58 判断随机数是否大于50,并用EL表达式输出测试结果。 <% int rand = (int)(Math.random()*100); pageContext.setAttribute("rand", rand); %> welcome you! 测试结果为: ${aa} 总结 JSTL中只有判断,没有else判断。如果需要if…else判断结构,可以用标签判断两次,如同时使用。 2. 标签配合使用,执行效果等同于Java脚本中的条件判断语句。 (1) 基本语法。 内容体 ( 子标签) 中可以放1~n个标签,即至少要包含一个子标签,可以同时存在多个子标签。 中可以放0~1个子标签,即可以没有子标签,最多只能有一个子标签。 (2) 基本语法。 内容体 test属性返回boolean值,决定内容体是否被处理。 不能单独使用,必须要有父标签。 必须要出现在标签的前面。 (3) 基本语法。 条件块 标签体内,如果没有就返回真,则JSP容器处理中的条件块。 不能单独使用,必须要有父标签。 体内,必须出现在最后。 示例59 示例效果等同于if…else if…else if…else,只要任何一个test返回真,就不再向下判断,执行内容体后,立即跳出 ... ... ... ... 示例510 示例效果等同于if…else。 No records matched your selection. ${count} records matched your selection. 视频讲解 视频讲解 5.2.3迭代标签 标签在JSP页面迭代输出集合中的数据,与Java脚本中的for()循环功能类似,基本语法如下,属性信息见表56。 内容体 表56属性信息 属性名动 态 支 持属 性 类 型描述 varfalseString迭代变量名 itemstrue参见集合说明迭代的集合对象 varStatusfalseString显示迭代状态,参见LoopTagStatus接口 begintrueint迭代操作时,集合的起始索引 endtrueint迭代操作时,集合的结束索引 steptrueint迭代操作的步长值 说明信息: begin索引必须大于或等于0。 如果end指定的索引值小于begin,则迭代不会执行。 步长值step必须大于或等于1。 如果items集合为null,不会抛出异常,按照空集合处理,即迭代不会执行。 items支持如下集合类型: 基本类型的静态数组(迭代时会自动使用包装类)。 java.util.Collection接口的实现类(会调用iterator()方法迭代集合)。 java.util.Iterator接口的实现类。 java.util.Enumeration接口的实现类。 java.util.Map接口实现类,var变量的类型为java.util.Map.Entry。 通用分隔符隔开的一个字符串。 1. 集合迭代 迭代静态数组、java.util.Collection、java.util.Iterator等集合对象。 示例511 迭代输出产品集合中的产品信息。 产品名: ${product.name} 价格: ${product.price} 示例512 迭代输出顾客信息,并在中显示。
顾客: ${ct.name}
2. Map迭代 当items类型为java.util.Map时,每个item的类型是java.util.Map.Entry。它有两个属性: key 和 value。 示例513 元素key是: ${entry.key}
元素value是: ${entry.value}
示例514 如下代码中的${entry.value}表示User对象,${entry.value.uname}表示用户名。 <% Map map = new HashMap(); map.put("tom", new User("tom")); map.put("jack", new User("jack")); map.put("rose", new User("rose")); request.setAttribute("map",map); %>
${entry.key} ${entry.value.uname}
示例515 使用嵌套读取Map数据,${aParam.value}是集合对象。 参数名: ${aParam.key} 参数值: ${aValue}
3. 迭代状态 使用varStatus显示当前迭代状态。迭代状态的操作依赖接口jakarta.servlet.jsp.jstl.core.LoopTagStatus,接口定义如下: public interface LoopTagStatus { java.lang.IntegergetBegin(); intgetCount(); java.lang.ObjectgetCurrent(); java.lang.IntegergetEnd(); intgetIndex(); java.lang.IntegergetStep(); booleanisFirst(); booleanisLast(); } getBegin: 返回迭代的begin属性值,如果begin属性不存在,就返回null。 getCount: 返回环绕迭代集合的当前数量。count是个相对值,从1开始。例如迭代某个集合,begin=5,end=15,step=5,则 counts 值分别为1、2、3。 getCurrent: 返回当前正在迭代的对象。 getEnd: 返回迭代的end属性值,如果end属性不存在,则返回null。 getIndex: 返回环绕迭代集合的当前索引值,索引从0开始。 getStep: 返回迭代的step属性值,如果step属性不存在,则返回null。 isFirst:如果当前的迭代项是集合的第一项,则返回true。 isLast:如何当前的迭代项是集合的最后一项,则返回true。 示例516 <% int[] sz = new int[]{10,12,35,24,65}; request.setAttribute("sz",sz); %>
${st.count} ${st.index} ${item}
输出结果如下: 1010 21 3235 43 5465 4. 范围属性 使用属性begin、end、step,可以在迭代集合时选择部分内容处理。 示例517 <% int[] sz = new int[]{10,12,35,24,65,78,102,205,12,31,20,309}; request.setAttribute("sz",sz); %>
${st.count} ${st.index} ${item}
输出结果如下: 1235 2465 36102 4812 51020 5.2.4URL相关标签 在JSP页面链接、导入、重定向到其他URL资源,在JSTL中统称为URL相关标签。 1. 基本语法如下,属性信息见表57。 表57属性信息 属性名动 态 支 持属 性 类 型描述 valuetrueString要处理的URL contexttrueString相对路径的URL依赖的外部Context名字 varfalseString输出到scope对象的变量名 scopefalseString域对象 与锚点不同,它用于生成访问资源的URL,但是并不会产生超链接。value属性值可以使用绝对地址,也可使用相对地址。绝对地址不会重写,而相对地址在解析时会重写,会自动增加context前缀。如,假设Web站点context为: /foo,则输出结果: /foo/ads/logo.html。 示例518 重写图片的相对路径,当前站点是/Hello,则图片链接为/Hello/pic/flex.png。 等效于 等效于 flex图片 示例519 设置URL资源后,将它存储在域对象中,然后通过EL表达式读取。 示例520 url设置context属性后,强制指向外部context,图片指向/Center/pic/flex.png。 2. 用于导入基于URL的资源,基本语法如下,属性信息见表58。 可选内容体 子标签 表58属性信息 属性名动态支持属性类型描述 urltrueString待导入资源的URL,可以是相对路径,也可以是绝对路径 contexttrueString当使用相对路径访问外部context资源时,指明外部context的名字 varfalseString用于存储所引入文本的变量 scopefalseStringvar属性存储在哪个域对象 charEncodingtrueString引入资源的字符编码 说明: 如果url为null、空串或无效,JspException异常被抛出; 如果charEncoding为null或空串,这个配置会被忽略; 的功能相似,但是只能嵌入当前Web应用的资源,而还可以导入外部资源。 示例521 嵌入头文件。 (1) 编写头文件head.jsp。 welcome ${user.uname} (2) 在hello.jsp中嵌入head.jsp。 hello! 示例522 使用绝对地址,导入外部资源文件。 3. 表示发送HTTP的redirect到客户端,与调用HttpServletResponse.sendRedirect()相同,基本语法如下,属性见表59。 表59属性信息 属性名动态支持属性类型描述 urltrueString重定向的目标URL,绝对地址和相对地址都可以 contexttrueString当使用相对路径访问外部context资源时,指明外部context的名字 示例523 用户登录后,根据身份不同,跳转到不同的页面。 4. 表示添加请求参数给URL,在中都可以使用,基本语法如下,属性信息见表510。 表510属性信息 属性名动 态 支 持属 性 类 型描述 nametrueStringHTTP请求参数名 valuetrueStringHTTP请求参数值 示例524 使用与URL中直接绑定参数的效果相同: 5.3格式化标签库 在JSP页面显示数字、货币、百分比、日期、时间等数据时,需要按照本地敏感或定制格式显示,这时使用格式化标签库非常方便。 5.3.1格式化数字、货币、百分比 标签可以格式化数字、货币、百分比,基本语法如下: 示例525 <%@ taglib prefix="fmt" uri="jakarta.tags.fmt"%> 输出结果(自动按本地的货币格式显示): ¥9,876,543.21。 如果设置本地化环境为en_US,则输出结果为美国货币格式: $9,876,543.21。 示例526 <% int rand = (int)(Math.random()*100); request.setAttribute("rand", rand); %> 输出结果(保留两位小数): 25.33 12.30 5.3.2格式化日期和时间 使用标签可以在JSP页面格式化日期和时间,基本语法如下: 示例527 <%@ taglib prefix="fmt" uri="jakarta.tags.fmt"%>
输出结果: 28/02/2020 2020-02-2820:46 5.4本章习题 (1) 下列不属于核心库标签的是()。 A. chooseB. ifC. fmtD. otherwise (2) 下面不属于JSTL标签的是()。 A. 核心标签库B. 国际化/格式化标签库 C. HTML标签库D. SQL标签库 E. 函数标签库 (3) 以下代码配置了一个自定义标签,这段代码应该位于()。 Spring Framework JSP Tag Library 4.0 spring http://www.springframework.org/tags A. Tomcat的conf/server.xml文件中 B. Jakarta Web应用的WEBINF/web.xml文件中 C. 一个tld文件中 D. Jakarta Web应用的METAINF/context.xml文件中 (4) 以下不属于标签属性的是()。 A. varB. valueC. itemsD. varStatus (5) 如下数据类型中,标签不能迭代的是()。 A. java.util.CollectionB. 静态数组 C. java.util.Map D. org.w3c.dom.Node E. java.util.Iterator (6) 以下不属于标签属性的是()。 A. varB. valueC. escapeXmlD. default (7) 标签与<%=脚本表达式 %> 或 ${el表达式}的功能基本一致。(对/错) (8) 使用标签,可以把指定的值存储到pageContext域对象中。(对/错) (9) 中至少要包含一个子标签和一个 。(对/错) (10) 导入资源,url可以是绝对路径也可以是相对路径。(对/错)