JavaWeb详解(第六篇)之JSTL标签简介

Posted 穆瑾轩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaWeb详解(第六篇)之JSTL标签简介相关的知识,希望对你有一定的参考价值。

JavaWeb详解(第六篇)之JSTL标签简介

1、JSTL概述

1.1、什么是JSTL

JSTL全称是指JavaServer Pages Standard Tag Library(JSP 标准标签库),提供了一系列的JSP标签,可以应用于各种领域,如:基本输入输出、流程控制、循环、XML 文件剖析、数据库查询及国际化和文字格式标准化的应用等,是一个不断完善的开放源代码的 JSP 标签库。

JSTL 由五个不同功能的标签库组成:

功能范围URI前缀
核心标签库--重点Oracle Java Technologies | Oraclec
格式化Oracle Java Technologies | Oraclefmt
函数Oracle Java Technologies | Oraclefn
数据库(不使用)Oracle Java Technologies | Oraclesql
XML(不使用)Oracle Java Technologies | Oraclex

1.2、为什么要使用JSTL

    EL 表达式主要是为了替换 jsp 中的表达式脚本, 而代码脚本这些并没有得到很好的优化,为了取代传统直接在页面上嵌入 Java 程序的做法,以提高程序可读性、维护性和便捷性,于是有了JSTL标签库,它使得整个 jsp 页面变得更佳简洁。

1.3、如何使用

1)先导入 jstl 标签库的 jar 包

注:下载地址

taglibs-standard-impl-1.2.5.jar
taglibs-standard-spec-1.2.5.jar(tomcat也需要此包)

2)第二步, 使用 taglib 指令引入标签库

<!--CORE 标签库-->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!--FMT 标签库-->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!--FUNCTIONS 标签库-->
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!--XML 标签库-->
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<!--SQL 标签库-->
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

2、core标签库的使用

    core标签库是JSTL的核心标签库,实现了最基本的功能:流程控制、迭代输出等操作

核心标签主要有:

标签描述
<c:if>构造简单的“if-then”结构的条件表达式
<c:choose>指定多个条件选择的组合边界,它必须与<c:when><c:otherwise>标签一起使用
<c:when><c:choose>的子标签,用来判断条件是否成立
<c:otherwise><c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行
<c:forEach>基础迭代标签,接受多种集合类型
<c:forTokens>根据指定的分隔符来分隔内容并迭代输出
<c:out>输出一段文本到浏览器中
<c:set>把某一个对象存在指定的域范围内
<c:remove>用于删除数据
<c:catch>用于捕获嵌套在标签体中的内容抛出的异常
<c:url>在JSP页面中构造一个URL地址
<c:import>检索一个绝对或相对 URL,然后将其内容暴露给页面
<c:redirect>重定向至一个新的URL
<c:param>用来给包含或重定向的页面传递参数

2.1、c:if

<c:if>标签用于简单的条件语句。

<c:if>标签的属性:

属性描述是否必要默认值
test条件
var用于存储条件结果的变量
scopevar属性的作用域page

 使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>jstl_core.jsp</h1>
    <%
        request.setAttribute("i", 12);
    %>
    <%--test属性必须存在--%>
    <c:if test="${empty param.user}">
        <h3>没有获取到user参数</h3>
    </c:if>
    <c:if test="${i==12}">
        <h3>12==12</h3>
    </c:if>
    <%     
        String amind="Admin";   
        request.setAttribute("amind",amind); 
    %>
    <%--var变量:用来存储test的评定结果,scope属性指定var变量的域--%>
    <c:if test="${requestScope.amind=='Admin'}" var="condition" scope="session">
  匹配正确哦
  </c:if><br>
   获取存储值sessionScope.condition:${sessionScope.condition}<br>
   获取存储值requestScope.condition:${requestScope.condition}
</body>
</html>

案例效果:  

2.2、c:choose、c:when、c:otherwise

    用于复杂判断的<c:choose>、<c:when>、<c:otherwise>标签

  <c:choose>标签没有属性,可以被认为是父标签, <c:when><c:otherwise>将作为其子标签来使用。

  <c:when>标签等价于“ if”语句,它包含一个 test属性,该属性表示需要判断的条件。

  <c:otherwise>标签没有属性,它等价于“ else”语句。

  <c:when>标签的属性:

属性描述是否必要默认值
test条件

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>jstl_core.jsp</h1>
     <c:choose>
        <c:when test="${sex eq 'M'}">
         男
        </c:when>
        <c:when test="${sex eq 'F'}">
         女
        </c:when>
        <c:otherwise>
         性别不明
        </c:otherwise>
    </c:choose>
</body>
</html>

2.3、c:forEach、c:forTokens

    JSTL所支持的迭代标签有两个,分别是<c:forEach><c:forTokens><c:forTokens>标签则通过指定分隔符将字符串分隔为一个数组然后迭代它们。

<c:forEach>标签有如下属性:

属性描述是否必要默认值
items要被循环的信息
begin开始的元素(0=第一个元素,1=第二个元素)0
end最后一个元素(0=第一个元素,1=第二个元素)Last element
step每一次迭代的步长1
var代表当前条目的变量名称
varStatus代表循环状态的变量名称

     <c:forTokens>标签与<c:forEach>标签有相似的属性,不过<c:forTokens>还有另一个属性:

属性描述是否必要默认值
delims分隔符

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="java.util.*"%>
<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>jstl_core.jsp</h1>
     <%--从“ 1”循环到“ 10”,并将循环中变量“ i”显示在页面上--%>
     <c:forEach var="i" begin="1" end="10" step="1">
         ${i}<br />
     </c:forEach>
     
     <%--输出10以内的质数--%>
     <c:forEach var="i" begin="1" step="2" end="10">
          ${i} 
     </c:forEach>
     <br>
     <%--遍历数组--%>
     <% 
         request.setAttribute("arr", new String[]{"18610541354","18688886666","18699998888"});
     %>
     <c:forEach items="${ requestScope.arr }" var="item">
         ${ item } <br>
     </c:forEach>
     
     <%
	     Map<String,Object> map = new HashMap<String, Object>();
	     map.put("key1", "value1");
	     map.put("key2", "value2");
	     map.put("key3", "value3");
         request.setAttribute("map", map);
     %>
     <%--遍历 Map 集合--%>
     <c:forEach items="${ requestScope.map }" var="entry">
		${entry.key} = ${entry.value}<br>
	 </c:forEach>
</body>
</html>

使用案例二:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="java.util.*"%>
<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>c:forTokens</h1>
    <span>遍历:google,runoob,taobao</span><br>
    <c:forTokens items="google,runoob,taobao" delims="," var="name">
       <c:out value="${name}"/><p>
    </c:forTokens>
</body>
</html>

案例效果:  

2.4、c:out

<c:out>用于在 JSP中显示数据就像是 <%= scripting-language %> 一样

<c:out>标签有如下属性:

属性描述是否必要默认值
value要输出的内容
default输出的默认值主体中的内容
escapeXml是否忽略XML特殊字符true

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>c:out</h1>
     以前的写法:
     <%out.println("hello world"); %>
     <%request.setAttribute("abc", "你好1");%><br>
     <%-- 如果属性域对象中有相同的属性名,c:out 的优先级是:
         pageContext>request>session>application
         它出色的地方就多了两个属性,default和escapeXml属性。
         如果我们用到这两个属性,我们就使用该标签,如果没有用到这两个属性就用EL表达式就可以了
     --%>
     <c:out value="hello world"></c:out>
     <c:out value="${abc}" default="没有值" escapeXml="false"></c:out> 
</body>
</html>

案例效果:

2.5、c:set

<c:set>标签用于为变量或 JavaBean中的变量属性赋值的工作

<c:set>标签有如下属性:

属性描述是否必要默认值
value要存储的值主体的内容
target要修改的属性所属的对象
property要修改的属性
var存储信息的变量
scopevar属性的作用域Page

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>c:out</h1>
     <c:set var="abc1" value="中国,北京" scope="request"></c:set>
     <c:out value="${abc1 }"></c:out><br>
     等价于:
     <% 
         request.setAttribute("abc", "中国,北京");
     %>
     ${abc }
</body>
</html>

2.6、c:remove

<c:remove>标签用于删除存在于 scope中的变量。

<c:remove>标签有如下属性:

属性描述是否必要默认值
var要移除的变量名称
scope变量所属的作用域所有作用域

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>c:remove</h1>
     <c:set var="name" scope="session" value="username"/>
     <p>name 变量值: <c:out value="${name}"/></p>
     <c:remove var="name"/>
     <p>移除 name 变量后的值: <c:out value="${name}"/></p>
</body>
</html>

2.7、c:catch

<c:catch>用于异常捕获

<c:catch>标签有如下属性:

属性描述是否必要默认值
var用来储存错误信息的变量None

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>c:catch</h1>
     <c:catch var="myexception">
      <%int a=9/0; %>
     </c:catch>
     <c:out value="${myexception}"></c:out>
</body>
</html>

案例效果:

2.8、c:url

<c:url>标签将URL格式化为一个字符串,然后存储在一个变量中。

<c:url>标签有如下属性:

 

属性描述是否必要默认值
value基础URL
context本地网络应用程序的名称当前应用程序
var代表URL的变量名Print to page
scopevar属性的作用域Page

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>c:url</h1>
    <%-- 产生一个字符串,并不是一个可以点的链接,并把他存入var的遍历中 --%>
    <c:url value="http://www.baidu.com" var="bd"/>
    ${bd }
    <br>
    <a href="${bd }">百度一下</a>
</body>
</html>

2.9、c:import

<c:import>标签提供了所有<jsp:include>行为标签所具有的功能,同时也允许包含绝对URL。

<c:import>标签有如下属性:

属性描述是否必要默认值
url待导入资源的URL,可以是相对路径和绝对路径,并且可以导入其他主机资源
context当使用相对路径访问外部context资源时,context指定了这个资源的名字。当前应用程序
charEncoding所引入的数据的字符编码集ISO-8859-1
var用于存储所引入的文本的变量
scopevar属性的作用域page
varReader可选的用于提供java.io.Reader对象的变量

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>c:import</h1>
    <c:import url="/el.jsp"></c:import>
    <hr>
    <c:import url="http://www.baidu.com" var="thisPage" charEncoding="UTF-8"/>
    <a href="${thisPage }"></a>
</body>
</html>

案例效果:

2.10、c:redirect、c:param

<c:redirect>用于页面的重定向,该标签的作用相当于 response.setRedirect方法的工作。并且支持<c:param>标签。

<c:param>用来为包含或重定向的页面传递参数。可用于<c:url><c:redirect>中。

<c:redirect>标签有如下属性:

属性描述是否必要默认值
url目标URL
context紧接着一个本地网络应用程序的名称当前应用程序

<c:param>标签有如下属性:

属性描述是否必要默认值
nameURL中要设置的参数的名称
value参数的值Body

使用案例:

<%@ page contentType="text/html;charset=GBK" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>c:redirect</h1>
    <c:redirect url="el.jsp">
        <c:param name="userName" value="RW" />
    </c:redirect>
</body>
</html>

 案例效果:

 3、fmt标签库的使用

    fmt标签库,提供了对国际化(I18N)的支持,它可以根据发出请求的客户端地域的不同来显示不同的语言,所以也叫做国际化标签库。同时还提供了格式化数据和日期的方法。

fmt标签主要有:

标签描述
<fmt:formatNumber>使用指定的格式或精度格式化数字
<fmt:parseNumber>解析一个代表着数字,货币或百分比的字符串
<fmt:formatDate>使用指定的风格或模式格式化日期和时间
<fmt:parseDate>解析一个代表着日期或时间的字符串
<fmt:bundle>绑定资源
<fmt:setLocale>指定地区
<fmt:setBundle>绑定资源
<fmt:timeZone>指定时区
<fmt:setTimeZone>指定时区
<fmt:message>显示资源配置文件信息
<fmt:requestEncoding>设置request的字符编码

3.1、fmt:formatNumber

<fmt:formatNumber>用于格式化数字,百分比,货币。

<fmt:formatNumber>标签有如下属性:

属性描述是否必要默认值
value要显示的数字
typeNUMBER,CURRENCY,或 PERCENT类型Number
pattern指定一个自定义的格式化模式用与输出
currencyCode货币码(当type="currency"时)取决于默认区域
currencySymbol货币符号 (当 type="currency"时)取决于默认区域
groupingUsed是否对数字分组 (TRUE 或 FALSE)true
maxIntegerDigits整型数最大的位数
minIntegerDigits整型数最小的位数
maxFractionDigits小数点后最大的位数
minFractionDigits小数点后最小的位数
var存储格式化数字的变量Print to page
scopevar属性的作用域page

使用案例:

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>fmt:formatNumber</h1>
    <%-- <fmt:setLocale value="zh_CN"/> 
        注:如果要实现国际化,那么编码格式要设置为utf-8,否则¥符号无法显示
    --%>
    <c:set var="balance" value="120000.2309" />
    
    <p>Formatted Number (1): <fmt:formatNumber value="${balance}"
            type="currency"/></p>
    <p>Formatted Number (2): <fmt:formatNumber type="number"
            maxIntegerDigits="3" value="${balance}" /></p>
    <p>Formatted Number (3): <fmt:formatNumber type="number"
            pattern="#,#00.0#" value="${balance}" /></p>
    <p>Formatted Number (7): <fmt:formatNumber type="percent"
            maxIntegerDigits="3" value="${balance}" /></p>      
            
    <p>Currency in USA :
    <fmt:setLocale value="en_US"/>
    <fmt:formatNumber value="${balance}" type="currency"/></p>
</body>
</html>

案例效果:

 3.2、fmt:formatDate

<fmt:formatDate>标签用于使用不同的方式格式化日期。

<fmt:formatDate>标签有如下属性:

属性描述是否必要默认值
value要显示的日期
typeDATE, TIME, 或 BOTHdate
dateStyleFULL, LONG, MEDIUM, SHORT, 或 DEFAULTdefault
timeStyleFULL, LONG, MEDIUM, SHORT, 或 DEFAULTdefault
pattern自定义格式模式
timeZone显示日期的时区默认时区
var存储格式化日期的变量名显示在页面
scope存储格式化日志变量的范围页面

使用案例:

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>fmt:formatDate</h1>
	<c:set var="now" value="<%=new java.util.Date()%>" />
	<p>日期格式化 (1): <fmt:formatDate type="time" 
	            value="${now}" /></p>
	<p>日期格式化 (2): <fmt:formatDate type="date" 
	            value="${now}" /></p>
	<p>日期格式化 (3): <fmt:formatDate type="both" 
	            value="${now}" /></p>
	<p>日期格式化 (4): <fmt:formatDate type="both" 
	            dateStyle="short" timeStyle="short" 
	            value="${now}" /></p>
	<p>日期格式化 (5): <fmt:formatDate type="both" 
	            dateStyle="medium" timeStyle="medium" 
	            value="${now}" /></p>
	<p>日期格式化 (6): <fmt:formatDate type="both" 
	            dateStyle="long" timeStyle="long" 
	            value="${now}" /></p>
	<p>日期格式化 (7): <fmt:formatDate pattern="yyyy-MM-dd" 
	            value="${now}" /></p>
</body>
</html>

案例效果:

 

4、functions标签库的使用 

    JSTL Functions标签库包含一系列标准函数(EL函数),大部分是通用的字符串处理函数。

 

函数描述
fn:contains()测试输入的字符串是否包含指定的子串
fn:containsIgnoreCase()测试输入的字符串是否包含指定的子串,大小写不敏感
fn:endsWith()测试输入的字符串是否以指定的后缀结尾
fn:escapeXml()跳过可以作为XML标记的字符
fn:indexOf()返回指定字符串在输入字符串中出现的位置
fn:join()将数组中的元素合成一个字符串然后输出
fn:length()返回字符串长度
fn:replace()将输入字符串中指定的位置替换为指定的字符串然后返回
fn:split()将字符串用指定的分隔符分隔然后组成一个子字符串数组并返回
fn:startsWith()测试输入字符串是否以指定的前缀开始
fn:substring()返回字符串的子集
fn:substringAfter()返回字符串在指定子串之后的子集
fn:substringBefore()返回字符串在指定子串之前的子集
fn:toLowerCase()将字符串中的字符转为小写
fn:toUpperCase()将字符串中的字符转为大写
fn:trim()移除首尾的空白符

使用案例:

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<!DOCTYPE html>
<html>
<head>
<title>jstl_core.jsp</title>
</head>
<body>
    <h1>fn:functions</h1>
    <p>containsIgnoreCase函数:${fn: containsIgnoreCase ("Tomcat","CAT")}</p>
    <p>startsWith函数:${fn: startsWith ("Tomcat","Tom")}</p>
    <p>indexOf函数:${fn: indexOf ("Tomcat","cat")}</p>
    <p>substring函数:${ fn: substring ("Tomcat",0,3)}</p>
</body>
</html>

案例效果:  

5、xml标签库的使用

    JSTL XML标签库提供了创建和操作XML文档的标签。

标签描述
<x:out>与<%= ... >,类似,不过只用于XPath表达式
<x:parse>解析 XML 数据
<x:set>设置XPath表达式
<x:if>判断XPath表达式,若为真,则执行本体中的内容,否则跳过本体
<x:forEach>迭代XML文档中的节点
<x:choose><x:when><x:otherwise>的父标签
<x:when><x:choose>的子标签,用来进行条件判断
<x:otherwise><x:choose>的子标签,当<x:when>判断为false时被执行
<x:transform>将XSL转换应用在XML文档中
<x:param><x:transform>共同使用,用于设置XSL样式表

6、sql标签库的使用

    JSTL SQL标签库提供了与关系型数据库(Oracle,mysql,SQL Server等等)进行交互的标签。

标签描述
<sql:setDataSource>指定数据源
<sql:query>运行SQL查询语句
<sql:update>运行SQL更新语句
<sql:param>将SQL语句中的参数设为指定值
<sql:dateParam>将SQL语句中的日期参数设为指定的java.util.Date 对象值
<sql:transaction>在共享数据库连接中提供嵌套的数据库行为元素,将所有语句以一个事务的形式来运行

    由于xml、和sql标签库用的并不多,我们着重介绍一下自定义标签。

7、自定义标签

7.1、为什么要使用自定义标签

    JSTL标签库只提供了简单的输出等功能,这些功能毕竟有限,有很多复杂的逻辑可能并不好用这些标准的标签库去实现,所以呢需要自定义标签。在Struts中也有自己的一套标签。

7.2、如何去实现自定义标签

    我们去观察下标准标签库中已有的core标签库,他有一些实体类和一个c.tld。

 

 所以要实现自定义标签需要做:

1)定义一个类,现实相应的接口;

2)在项目的WEB-INF文件夹中新建一个tld文件;

要想让一个类成为标签类,就必须实现Jsptag接口,目前已知的实现类及接口有:

a)如果要自定义一个标签我们需要去实现Tag接口或SimaapleTag接口;

b)如果要自定义一个有标签体有属性的标签,继承 BodyTagSupport类

c)如果要自定义一个没有标签体的标签,继承TagSupport类

当然看自己需求,决定使用哪个接口或类。

7.3、自定义标签的生命周期

首先我们看一个案例:

1)新建一个MyTag1类实现Tag接口

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;

public class MyTag1 implements Tag{
	/**
	 * 当WEB容器执行到自定义标签的结束标记时,调用doEndTag()方法
	 */
	@Override
	public int doEndTag() throws JspException {
		System.out.println("我调用了doEndTag");
		return 0;
	}
	/**
	 * 当WEB容器执行到自定义标签的开始标记时,调用doStartTag()方法
	 */
	@Override
	public int doStartTag() throws JspException {
		System.out.println("我调用了doStartTag");
		return 0;
	}
	
	@Override
	public Tag getParent() {
		return null;
	}
	/**
	 * 当WEB容器执行完自定义标签后,标签处理器类会驻留在内存中,直至停止WEB应用时,WEB容器才会调用release()方法
	 */
	@Override
	public void release() {
		System.out.println("我调用了release");
	}
	
	/**
	 * 由服务器调用将pageContext对象传递给标签处理器类,
	 * 使得标签处理器类可以通过pageContext对象与JSP页面进行通信
	 */
	@Override
	public void setPageContext(PageContext arg0) {
		System.out.println("我调用了setPageContext");
	}
	/**
	 * setPageContext()后调用,如果当前标签没有父标签,则传入null
	 */
	@Override
	public void setParent(Tag arg0) {
		System.out.println("我调用了setParent");
	}
}

 2)新建一个myTag.tld

<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1">
    <tlib-version>1.2</tlib-version>
    <short-name>my</short-name>
    <uri>http://www.mytag.com</uri>
    
    <tag>
        <name>mytag1</name>
        <tag-class>com.cn.tag.MyTag1</tag-class>
        <!--标签体内容:
            empty:无标签体
            scriptless:标签体可以包含 el 表达式和 JSP 动作元素,但不能包含 JSP 的脚本元素
            tagdependent:表示标签体交由标签本身去解析处理。
            JSP:jsp2.0已不支持,表示可以是java脚本、标签,也可以是el表达式
        -->
        <body-content>empty</body-content>
    </tag>
</taglib>  

3)新建一个myjstl.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@taglib prefix="my" uri="http://www.mytag.com" %>
<!--引入这个标签库使用的uri-->
<!DOCTYPE html>
<html>
<head>
<title>myjstl.jsp</title>
</head>
<body>
    <h1>自定义标签</h1>
   <p><my:mytag1/></p>
</body>
</html>

4)案例执行效果

整个执行过程:

a)JSP引擎遇到自定义标签,首先创建标签处理器类的实例对象;

b)然后调用setPageContext()方法,将pageContext对象传递给标签处理器类,使得标签处理器类可以通过pageContext对象与JSP页面进行通信;

c)setPageContext()方法执行完后,调用setParent()方法,将当前标签的父标签传递给当前处理器类,如果当前标签没有父标签,则传入null;

d)当WEB容器执行到自定义标签的开始标记时,调用doStartTag()方法;

e)当WEB容器执行到自定义标签的结束标记时,调用doEndTag()方法;

f)当WEB容器执行完自定义标签后,标签处理器类会驻留在内存中,直至停止WEB应用时,WEB容器才会调用release()方法;

7.4、自定义标签的实现

7.4.1、TagSupport类实现自定义标签

    TagSupport是Tag的一个模板类,实现了pageContext,parent的getter、setter方法以及一些其他的功能。

使用案例:

1)新建一个MyTag2类继承TagSupport

package com.cn.tag;

import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

public class MyTag2 extends TagSupport{

	private String defaultValue;
	private String value;

	/**
	 * 属性对应的方法
	 * @param value
	 */
    public void setValue(String value) {
        this.value = value;
    }
	
    /**
	 * 属性对应的方法
	 * @param value
	 */
	public void setDefaultValue(String defaultValue) {
		this.defaultValue = defaultValue;
	}

	@Override
	public int doEndTag() throws JspException {
		// TODO Auto-generated method stub
		return super.doEndTag();
	}

	/**
	 * 标签中静态常量:
	 * EVAL_BODY_INCLUDE:告诉服务器正文的内容,并把这些内容送入输出流
	 * SKIP_BODY:告诉服务器不要处理正文内容
	 * EVAL_PAGE:让服务器继续执行页面
	 * SKIP_PAGE:让服务器不要处理剩余的页面
	 * EVAL_BODY_AGAIN:让服务器继续处理正文内容,只有doAfterBody方法可以返回
	 * EVAL_BODY_BUFFERED:BodyTag接口的字段,在doStartTag()返回
	 * 
	 * EVAL_BODY_INCLUDE、SKIP_BODY一般由doStartTag()返回,
	 * 而EVAL_PAPGE、SKIP_PAGE由doEndTag()返回
	 */
	@Override
	public int doStartTag() throws JspException {
		 //获取到request对象
		String str = value;
        if (value == null || "".equals(value)) {
            str = defaultValue;
        }
        JspWriter jspWriter = pageContext.getOut();
        try {
			jspWriter.write(str);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return SKIP_BODY;
	}
	
}

2)myTag.tld中加入

<tag>
        <name>mytag2</name>
        <tag-class>com.cn.tag.MyTag2</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>value</name>
            <required>true</required>
            <!-- 是否支持表达式 -->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
	    <attribute>
		    <name>defaultValue</name>
		    <required>false</required>
		    <rtexprvalue>true</rtexprvalue>
	    </attribute>
    </tag>

3)使用自定义标签

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@taglib prefix="my" uri="http://www.mytag.com" %>

<!DOCTYPE html>
<html>
<head>
<title>myjstl.jsp</title>
</head>
<body>
    <h1>自定义标签</h1>
   <p><my:mytag2 value="myValue"/></p>
   <p><my:mytag2 value="" defaultValue="default"/></p>
</body>
</html>

4)案例效果

  

 7.4.2、BodyTagSupport类实现自定义标签

    BodyTagSupport继承了TagSupport类实现了BodyTag接口,也能获取到标签体的内容,所以说如果要自定义一个有标签体有属性的标签,应该继承 BodyTagSupport类。

    他的生命周期:doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()

使用案例:

1)新建一个MyTag3类

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class MyTag3 extends BodyTagSupport{

	@Override
	public BodyContent getBodyContent() {
		return super.getBodyContent();
	}

	public int doAfterBody() throws JspException {
		// TODO Auto-generated method stub
		BodyContent content = getBodyContent();
		String str = content.getString();
		System.out.println(str);
		if(str != null){
			 String name = "";
			 if(str.startsWith("$toUpperCase(") && str.endsWith(")"))
		        {
				    String para = str.substring(13,str.length()-1);
				    if(para!=null && !"".equals(para)) {
				    	name = para.toUpperCase();
				    }
		        }
		    JspWriter out = getPreviousOut();
		try {
		    out.print(name==null?str:name);
		} catch (IOException e) {
	    	e.printStackTrace();
		 }
		}
		return SKIP_BODY;
	}

}

2)myTag.tld

<tag>
        <name>mytag3</name>
        <tag-class>com.cn.tag.MyTag3</tag-class>
        <body-content>scriptless</body-content>
    </tag>

3)myjstl.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib prefix="my" uri="http://www.mytag.com" %>

<!DOCTYPE html>
<html>
<head>
<title>myjstl.jsp</title>
</head>
<body>
    <h1>自定义标签</h1>
   <%
       request.setAttribute("key", "value");
      pageContext.setAttribute("key", "value1");
   %>
   <p>${key }</p>
   <my:mytag3>$toUpperCase(${key})</my:mytag3>
   
</body>
</html>

4)案例效果

 

以上是关于JavaWeb详解(第六篇)之JSTL标签简介的主要内容,如果未能解决你的问题,请参考以下文章

10.javaweb核心标签库详解

JavaWeb 之 JSTL 标签

Java实战之04JavaWeb-04JSPEL表达式JSTL标签库

JAVAWEB开发之JSTL标签库的使用 自己定义EL函数自己定义标签(带属性的带标签体的)

JavaWeb之JSTL标签库

JavaWeb学习笔记11--JSTL标签库