4.jstl
0.jstl标签介绍
JavaServer Pages标准标记库(JSTL)是一个有用的JSP标签的集合,它封装了许多JSP应用程序通用的核心功能。
一、作用:JSTL支持常见的,结构性任务,如迭代和条件,标签为操纵XML文件,国际化标签和SQL标签。
它还提供了一个框架,将现有的自定义标签和JSTL标签。
二、组成
JSTL标签进行分类,根据其功能分为以下,可用于创建一个JSP页面时,JSTL标签库组:
1.核心标签(Core Tags)
2.格式化标签(Formatting tags)
3.SQL标签(SQL tags)
4.XML标签(XML tags)
5.JSTL函数(JSTL Functions)
三、安装JSTL库:
1.如果您使用的是Apache Tomcat容器,那么按照下面两个简单的步骤:
下载的二进制发行版,从Apache标准标记库和解压的压缩文件。
使用标准的标签库从Jakarta Taglibs分布,复制发行版'lib'目录到应用程序的JAR文件 webapps\ROOT\WEB-INF\lib 目录中。
要使用JSTL库,要在每一个JSP的顶部,使用该库必须包括一个<taglib>指令。
2.在开发中使用时注意:使用MyEclipse,不需要我们自己导入jar包,jar在创建项目的时候自动导入;
如果使用的是eclipse必须自己导入。
jar包:jstl-1.2.jar,standard-1.1.2.jar(不是必须)
1.c核心标签
一、在页面导入JSTL核心标签库
<%taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
注意,使用时会出现两种标签库,建议使用第二种
JSTL1.0 的声明是:<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
JSTL1.1 的声明是:<%@ taglib prefix="c" uri=http://java.sun.com/jsp/jstl/core %>
二、常用的标签
1.<c:set>
<c:set var="a" value="hello"/> 创建名为a,值为hello的域属性,范围:page
<c:set var="a" value="hello" scope="session"/> scope指定作用域session,request,page
2.<c:out>
<c:out value="aaa"/> 输出字符串aaa
<c:out value="${aaa }"/> 输出域属性aaa,其中与${aaa}相同
<c:out value="${aaa }" default="没有找到值"/> 如果${aaa}不存在,那么输出xxx字符串
<c:out value="${aaa }" escapeXml="true"/> 如果${aaa}中包含特殊字符,那么转义它。这可以防止javascript攻击
escapeXml的用法,如果:<c:set var="a" value="<font size=16>java</font>" />
<c:out value="${a }" escapeXml="true"></c:out>,默认为true,输出:<font size=16>java</font>
<c:out value="${a }" escapeXml="false"></c:out>,输出大字体大小为16的:java
3.<c:remove>
<c:remove var="a"/> 删除名为a的域属性
<c:remove var="a" scope="page"/> 删除page域中名为a的域属性
4.<c:url>
<c:url value="/AServlet"/> 输出URL:/项目名/AServlet
<c:url value="/AServlet" var="url" scope="page"/> 把生成的url保存到page域中,而不会输出
<c:url value="/AServlet"> 输出URL:/项目名/AServlet?username=%xx%xx%xx%xx%xx%xx,其中张三会被URL编码
<c:param name="username" value="张三"/>
</c:url/>
5.<c:if>
<c:if test="${user.id eq 1}"> 当条件为true时执行标签体内容
hello
</c:if>
6.<c:choose>
<c:choose>
<c:when test="${条件1}">a</c:when>
<c:when test="${条件2}">b</c:when>
<c:when test="${条件3}">c</c:when>
<c:otherwise>d</c:otherwise>
</c:choose>
等同与:
if() {
} esle if() {
} esle if() {
} else if() {
} else {
}
7.<c:forEach> 可以用来遍历数组、List、Map
(1). 计数循环,默认增加1
从1到10
<c:forEach begin="1" end="10" var="i">
${i}
</c:forEach>
等同于
for(int i = 1; i <= 10; i++) {
out.println(i);
}
从1到10,每次增加2
<c:forEach begin="1" end="10" var="i" step="2">
${i}
</c:forEach>
等同于
for(int i = 1; i <= 10; i+=2) {
out.println(i);
}
-------------
(2). 遍历数组
<%
String[] names = {"zhangSan", "liSi", "wangWu", "zhaoLiu"};
pageContext.setAttribute("ns", names);
%>
<c:forEach var="item " items="${ns } ">
<c:out value="name: ${item } "/><br/>
</c:forEach>
-------------
(3). 遍历List
<%
List<String> names = new ArrayList<String>();
names.add("zhangSan");
names.add("liSi");
names.add("wangWu");
names.add("zhaoLiu");
pageContext.setAttribute("ns", names);
%>
<c:forEach var="item" items="${ns }">
<c:out value="name: ${item }"/><br/>
</c:forEach>
-------------
(4). 遍历Map
<%
Map<String,String> stu = new LinkedHashMap<String,String>();
stu.put("number", "N_1001");
stu.put("name", "zhangSan");
stu.put("age", "23");
stu.put("sex", "male");
pageContext.setAttribute("stu", stu);
%>
<c:forEach var="item " items="${stu }">
<c:out value="${item.key }: ${item.value } "/><br/>
</c:forEach>
-------------
(5). 循环状态对象
循环状态对象是用来说明循环的状态的,属性如下:
count:int类型,当前以遍历元素的个数;
index:int类型,当前元素的下标;
first:boolean类型,是否为第一个元素;
last:boolean类型,是否为最后一个元素;
current:Object类型,表示当前对象。
<c:forEach var="item" items="${ns }" varStatus="vs" >
<c:if test="${vs.first } ">第一行:</c:if>
<c:if test="${vs.last } ">最后一行:</c:if>
<c:out value="第${vs.count } 行: "/>
<c:out value="[${vs.index } ]: "/>
<c:out value="name: ${vs.current } "/><br/>
</c:forEach>
三、其他C标签
1.<c:redirect>
<c:redirect url="http://www.baidu.com"/> 重定向到url,以get请求
2.<c:catch>标签捕获任何Throwable,发生在它的身上,有选择地公开。简单地用于错误处理,更优雅地处理这个问题。
<c:catch var ="catchException"> var是自定义的异常名称
<% int x = 5/0;%>
</c:catch>
<c:if test = "${catchException != null}">
<p>The exception is : ${catchException} <br />
There is an exception: ${catchException.message}</p>
</c:if>
3.<c:import>标记提供<include>的所有的功能动作,但也可以包含绝对URL
<c:import var="data" url="http://www.baidu.com"/>
<c:out value="${data}" escapeXml="false"/>
属性 描述 必需 默认值
url URL检索和导入到页面 Yes None
context /后面的本地Web应用程序的名称 No 目前的应用
charEncoding 为导入数据使用的字符集 No ISO-8859-1
var 变量的名称存储导入的文本 No Print to page
scope 变量作用域用于存储导入的文本 No Page
varReader 替代变量的名称,暴露的java.io.Reader No None
2.fmt格式化标签
一、导入JSTL格式化标签库
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
二、常用标签库
1.<fmt:formatDate>时间格式化,详细看《fmt formatDate标签.png》
<%
Date date = new Date();
pageContext.setAttribute("d", date);
%>
<fmt:formatDate value="${d }" pattern="yyyy-MM-dd HH:mm:ss "/>
2.<fmt:formatNumber>数字格式化,详细看《fmt formatNumber.png》
<%
double d1 = 3.5;
double d2 = 4.4;
pageContext.setAttribute("d1", d1);
pageContext.setAttribute("d2", d2);
%>
<fmt:formatNumber value="${d1 }" pattern="0.00 "/><br/>
<fmt:formatNumber value="${d2 }" pattern="#.## "/>
pattern:0.00,表示小数不足两位时,使用0补足两位
pattern:#.##,表示小数不足两位时,有几位显示几位,不会补足
三、i18n使用标签
1.国际化要使用语言文件,以properties为例。
message_zh_CN.properties保存中文
message_en_GB.properties保存英文
2.设置本地语言和国家等
<fmt:setLocale value="en_GB" />
<fmt:setLocale value="zh_CN" />
<fmt:setLocale value="${pageContext.request.locale}" />
3.导入文件束,在src下的文件,basename是文件名的前半部分,后半部分可不写,
<fmt:setBundle basename="message" var="propertiesName" />
4.调用值
<fmt:message bundle="${propertiesName }" key="sys.login.message"></fmt:message>
5.设置编码
<fmt:requestEncoding value="UTF-8" />
6.设置时区
<fmt:timeZone>
3.sql标签
一、JSTL的SQL标签库标签可以交互关系型数据库(如Oracle,MySQL或Microsoft SQL Server的关系数据库管理系统)。
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
已经过时了,不要使用啦。已经过时了,不要使用啦。已经过时了,不要使用啦。已经过时了,不要使用啦。
二、标签
1.注册数据源<sql:setDataSource>
<sql:setDataSource
var="account_db" //名称
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/accountbook?useUnicode=true&characterEncoding=utf8"
user="root"
password="root"
scope="page" //作用域
/>
2.<sql:query>查询
<sql:query
dataSource="${account_db}"
sql="select * from type"
var="result"
startRow="0" 该行的结果个数,在开始记录,默认0
maxRows="5" 结果存储在变量中的最大数目
/>
或:
<sql:query dataSource="${account_db}" var="result">
SELECT * from Employees;
</sql:query>
处理查询的结果,.rows就是查询结果,且返回的结果中是以数据库字段名称来调用属性值
<c:forEach items="${result.rows }" var="res">
${res.id }----${res.name }----${res.creTime }----${res.user_id }<br />
</c:forEach>
3.<sql:update>标签执行SQL语句不返回数据,例如SQL INSERT,UPDATE或DELETE语句
<sql:update dataSource="${account_db}" var="count">
INSERT INTO TYPE VALUES (8, 2, 'Nuha', 'Ali');
</sql:update>
4.<sql:transaction>
用于<sql:query>和<sql:update>组成事务。可以把尽可能多的<sql:query>和<sql:update>作为<sql:transaction>
内部语句来使他们成为一个单个事务。如果一个异常被任何嵌套的动作抛出,
它确保了嵌套的动作进行数据库的修改是提交或回滚
<sql:transaction dataSource="${account_db}">
<sql:update var="count">
UPDATE Students SET last = 'Ali' WHERE Id = 102
</sql:update>
<sql:update var="count">
UPDATE Students SET last = 'Shah' WHERE Id = 103
</sql:update>
<sql:update var="count">
INSERT INTO Students VALUES (104,'Nuha', 'Ali', '2010/05/26');
</sql:update>
</sql:transaction>
5.<sql:param>
与<sql:query>标签和<sql:update>标签嵌套使用,用来提供一个值占位符。如果是一个null值,则将占位符设为SQL NULL。
<c:set var="empId" value="103"/>
<sql:update dataSource="${account_db}" var="count">
DELETE FROM Employees WHERE Id = ?
<sql:param value="${empId}" />
</sql:update>
6.<sql:dateParam>//type DATE (只有日期),TIME(只有时间), TIMESTAMP (日期和时间)
标签与<sql:query>标签和<sql:update>标签嵌套使用,用来提供日期和时间的占位符。如果是一个null值,则将占位符设为SQL NULL。
<%
Date DoB = new Date("2001/12/16");
int studentId = 100;
%>
<sql:update dataSource="${snapshot}" var="count">
UPDATE Students SET dob = ? WHERE Id = ?
<sql:dateParam value="<%=DoB%>" type="DATE" />
<sql:param value="<%=studentId%>" />
</sql:update>
4.ELfn函数标签
一、导入函数库
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
二、EL函数库介绍
String toUpperCase(String input):转换成大写
String toLowerCase(String input):转换成小写
int indexOf(String input, String substring):返回大串中,小串的位置
boolean contains(String input, String substring):返回大串中是否包含小串
boolean containsIgnoreCase(String input, String substring):忽略大小写的是否包含
boolean startsWith(String input, String substring):是否以小串为前缀
boolean endsWith(String input, String substring):是否以小串为后缀
String substring(String input, int beginIndex, int endIndex):截取子串
String substringAfter(String input, String substring):截取小串后的部分!${fn:substringAfter(hello-world, "-")},输出为world
String substringBefore(String input, String substring):截取小串前面的部分
String escapeXml(String input):把字符串的">"、"<"。。。转义了!
String trim(String input):去除前后空格
String replace(String input, String substringBefore, String substringAfter):替换
String[] split(String input, String delimiters):分割字符串为数组
int length[用来返回字符串、数组、以及各种集合的长度](Object obj):可以获取字符串、数组、各种集合的长度!
String join(String array[], String separator):与split是相反的,使用指定分割符来连接数组,返回一个字符串。
三、案例
<%
String[] strs = {"a", "b","c"};
List list = new ArrayList();
list.add("a");
pageContext.setAttribute("arr", strs);
pageContext.setAttribute("list", list);
%>
${fn:length(arr) } <br/><!--3-->
${fn:length(list) } <br/><!--1-->
${fn:toLowerCase("Hello") } <br/> <!-- hello -->
${fn:toUpperCase("Hello") } <br/> <!-- HELLO -->
${fn:contains("abc", "a")} <br/><!-- true -->
${fn:containsIgnoreCase("abc", "Ab")} <br/><!-- true -->
${fn:contains(arr, "a")} <br/><!-- true -->
${fn:containsIgnoreCase(list, "A")} <br/><!-- true -->
${fn:endsWith("Hello.java", ".java")} <br/><!-- true -->
${fn:startsWith("Hello.java", "Hell")} <br/><!-- true -->
${fn:indexOf("Hello-World", "-")} <br/><!-- 5 -->
${fn:join(arr, ";")} <br/><!-- a;b;c -->
${fn:replace("Hello-World", "-", "+")} <br/><!-- Hello+World -->
${fn:join(fn:split("a;b;c;", ";"), "-")}<br/><!-- a-b-c -->
${fn:substring("0123456789", 6, 9)} <br/><!-- 678 -->
${fn:substring("0123456789", 5, -1)} <br/><!-- 56789 -->
${fn:substringAfter("Hello-World", "-")}<br/><!-- World -->
${fn:substringBefore("Hello-World", "-")}<br/><!-- Hello -->
${fn:trim(" a b c ")} <br/><!-- a b c -->
${fn:escapeXml("<html></html>")} <br/><!-- <html></html> -->
############################################################################################
一、自定义EL函数库
1.函数库的Java类
写一个类,写一个有返回值的静态方法;
编写itcast.tld文件,可以参数fn.tld文件来写,把itcast.tld文件放到/WEB-INF目录下;
在页面中添加taglib指令,导入自定义标签库。
2.或是将写好的函数库打成jar包
把tld文件放到META-INF下!
把jar包放到lib中
在jsp中<%@ taglib %>的uri给出tld中的<uri>
二、代码案例
1.静态方法
public class FunctionDemo {
public static String toUpperCase(String str){
return str.toUpperCase();
}
public static String go(){
System.out.println(str.toUpperCase());
return "go";
}
}
2.itcast.tld(默认是放在WEB-INF目录下)
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>cao</short-name>
<uri>http://www.cao.cn/cao</uri>
<function><!-- 定义函数1 -->
<name>toUppercase</name>
<function-class>com.jstl.FunctionDemo</function-class>
<function-signature>java.lang.String toUpperCase(java.lang.String)</function-signature>
</function>
<function><!-- 定义函数2 -->
<name>go</name>
<function-class>com.jstl.FunctionDemo</function-class>
<function-signature>java.lang.String go()</function-signature>
</function>
</taglib>
2.1、(可选步骤)前提是把tld文件放到了WEB-INF目录下。
告知应用,tld文件和tld中的uri的对应。修改web.xml,增加以下内容:
<jsp-config>
<taglib>
<taglib-uri>http://www.cao.cn/cao</taglib-uri>
<taglib-location>/WEB-INF/cao.tld</taglib-location>
</taglib>
</jsp-config>
3.index.jsp
<%@ taglib prefix="cao" uri="/WEB-INF/itcast.tld" %>
或<%@ taglib prefix="cao" uri="http://www.cao.cn/cao" %>
${cao:toUppercase("asdasdasd") }
${cao:go }
5.xml标签
已经过时了,不要使用啦。
6.el表达式
一、EL表达式简介
EL 全名为Expression Language。EL主要作用:
1、获取数据
EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象、获取数据。(某个web域 中的对象,访问javabean的属性、访问list集合、访问map集合、访问数组)
2、执行运算
利用EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算。${user==null}
3、获取web开发常用对象
EL 表达式定义了一些隐式对象,利用这些隐式对象,web开发人员可以很轻松获得对web常用对象的引用,从而获得这些对象中的数据。
4、调用Java方法
EL表达式允许用户开发自定义EL函数,以在JSP页面中通过EL表达式调用Java类的方法。
二、获取数据
使用EL表达式获取数据语法:"${标识符}"
EL表达式语句在执行时,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、session、application四个域中查找相应的对象,找到则返回相应对象,找不到则返回"" (注意,不是null,而是空字符串)。
EL表达式可以很轻松获取JavaBean的属性,或获取数组、Collection、Map类型集合的数据
${name}等同于pageContext.findAttribute("name")
三、常用用法
1.根据key取map集合的数据
${map.c}
${map["c"]}
2.获取list,set和数组
${list[1]}
3.迭代Map集合
<c:forEach var="me" items="${map}">
${me.key}=${me.value}
</c:forEach>
四、执行运算
+-*/四则运算符就不说啦
1.关系运算符,返回Boolean值
结合c标签使用,如:<c:if test="${1 == 1 }" ><span>ok</span></c:if>
${5 == 5}${5 eq 5}也是可以用来比较字符串${"a" == "a"}${"a" eq null}
${5 != 5}${5 ne 5}
${5 < 5}${5 lt 5}
${5 < 5}${5 gt 5}
${5 <= 5}${5 le 5}
${5 >= 5}${5 ge 5}
2、逻辑运算符:
${true && true}${true and true} true
${true || false}${true or false} true
${! true}${not true} false
3、empty运算符:检查对象是否为null(空)
<c:if test="${empty(emptyList)}">
对不起,没有您想看的数据
</c:if>
4、二元表达式:${user!=null?user.name :""}
5、[ ] 和 . 号运算符
五、获得web开发常用对象
EL表达式语言中定义了11个隐含对象,使用这些隐含对象可以很方便地获取web开发中的一些常见对象,并读取这些对象的数据。
语法:${隐式对象名称}:获得对象的引用
序号 隐含对象名称 描 述
1 pageContext 对应于JSP页面中的pageContext对象(注意:取的是pageContext对象。)
2 pageScope 代表page域中用于保存属性的Map对象
3 requestScope 代表request域中用于保存属性的Map对象
4 sessionScope 代表session域中用于保存属性的Map对象
5 applicationScope 代表application域中用于保存属性的Map对象
6 param 表示一个保存了所有请求参数的Map对象
7 paramValues 表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个string[]
8 header 表示一个保存了所有http请求头字段的Map对象,注意:如果头里面有"-" ,
例Accept-Encoding,则要header["Accept-Encoding"]
9 headerValues 表示一个保存了所有http请求头字段的Map对象,它对于某个请求参数,返回的是一个string[]数组。
注意:如果头里面有"-" ,例Accept-Encoding,则要headerValues["Accept-Encoding"]
10 cookie 表示一个保存了所有cookie的Map对象
11 initParam 表示一个保存了所有web应用初始化参数的map对象
${pageContext.request.contextPath } /20160605_http
六、使用EL调用Java方法
EL表达式语法允许开发人员开发自定义函数,以调用Java类的方法。语法:${prefix:method(params)}
在EL表达式中调用的只能是Java类的静态方法,这个Java类的静态方法需要在TLD文件中描述,才可以被EL表达式调用。
EL自定义函数用于扩展EL表达式的功能,可以让EL表达式完成普通Java程序代码所能完成的功能。
1、EL Function开发步骤
一般来说, EL自定义函数开发与应用包括以下三个步骤:
1、编写一个Java类的静态方法
2、编写标签库描述符(tld)文件,在tld文件中描述自定义函数。
3、在JSP页面中导入和使用自定义函数
2、开发EL Function注意事项
编写完标签库描述文件后,需要将它放置到<web应用>\WEB-INF目录中或WEB-INF目录下的除了classes和lib目录之外的任意子目录中。
TLD文件中的<uri> 元素用指定该TLD文件的URI,在JSP文件中需要通过这个URI来引入该标签库描述文件。
<function>元素用于描述一个EL自定义函数,其中:
<name>子元素用于指定EL自定义函数的名称。
<function-class>子元素用于指定完整的Java类名,
<function-signature>子元素用于指定Java类中的静态方法的签名,方法签名必须指明方法的返回值类型及各个参数的类型,各个参数之间用逗号分隔。
3、EL注意事项
EL表达式是JSP 2.0规范中的一门技术 。因此,若想正确解析EL表达式,需使用支持Servlet2.4/JSP2.0技术的WEB服务器。
注意:有些Tomcat服务器如不能使用EL表达式
(1)升级成tomcat6
(2)在JSP中加入<%@ page isELIgnored="false" %>
4.直接调用对象的方法
比如响应中有值为:money,他是一个BigDecimal类型的数据,如果想在页面上与整数
0判断,需要将对象转为int类型,我们可以调用他的intValue方法。
BigDecimal money == new BigDecimal(0.00);
${money.intValue() eq 0} 结果是页面打印 true
7.自定义jstl标签
一、标签的存在,用来替代<%...%>!(在jsp上,是禁止写java脚本的)
JSP到底要做些什么!(1. 收集用户的参数,传递给Servlet。2. 把Servlet的处理结果显示给用户看)
二、自定义标签
流程
1.写一个标签处理类
2.编写tld文件(标签库描述符)
3.JSP页面中<% taglib %>导入标签库
1.写一个标签处理类
Tag(老版本)、SimpleTag(JSP2.0提供的新接口)、继承TagSupport类
(1).Tag接口:其中的方法都是由容器调用的。
常量:
SKIP_BODY:忽略标签的主体内容。只为doStartTag方法服务
EVAL_BODY_INCLUDE:不忽略标签的主体内容。只为doStartTag方法服务
SKIP_PAGE:忽略结束标签之后的内容。只为doEndTag方法服务
EVAL_PAGE:不忽略结束标签之后的内容。只为doEndTag方法服务
方法:
int doStartTag():容器调用。遇到自定义标签的开始标签时被调用。
int doEndTag():容器调用。遇到自定义标签的结束时被调用。
void setPageContext(PageContext pc):由容器调用。处理标签之前就会调用。
void setParent(Tag t):由容器调用。处理标签之前就会调用。目标传递进父标签,没有传递null。
void release() :由容器调用,释放标签类占用的资源。
(2).IterationTag接口:继承Tag接口。增加重复执行主体内容的方法
int doAfterBody():执行完主体后会被容器调用该方法。
该方法的返回值只能是:Tag.SKIP_BODY,忽略主体,进入结束标签处理。
IterationTag.EVAL_BODY_AGAIN,再执行一次主体内容。
(3).BodyTag接口:继承IterationTag接口。增加了获取主体内容的方法。
int EVAL_BODY_BUFFERED:给doStartTag()方法用的。只有返回该值,以下2个方法才会被容器调用。
void doInitBody():初始化主体。容器调用
void setBodyContent(BodyContent b) :设置主体内容。容器调用。BodyContent就代表着主体内容。
(4).SimpleTag接口:*****jsp2.0添加,是目前jstl标签的实现接口
void doTag():每次执行标签时都会调用这个方法!容器调用。
JspTag getParent():获取父标签!(不是生命周期方法,没人会调用它,除了我们自己)
void setJspBody(JspFragment jspBody):容器调用。传入标签的主体内容。
void setJspContext(JspContext pc):容器调用。传入PageContext对象。
void setParent(JspTag parent):容器调用。传入父标签。
(5).继承SimpleTagSupport
void doTag():我们只需要完成这一个方法即可,其他的方法都被父类完成了。
SimpleTagSupport类还提供了一系列的get方法,用来获取tomcat传递进来"礼物"!
2.编写tld文件
<tag>
<!-- 标签名称 -->
<name>myTag1</name>
<!-- 标签处理类 -->
<tag-class>cn.itcast.tags.MyTag1</tag-class>
<!-- 标签体的类型,empty表示没有标签体 -->
<body-content>empty</body-content>
</tag>
3.在jsp中导入标签库
<%@ taglib prefix="" uri=""%>
三、自定义标签概述
1.自定义标签的步骤
其实我们在JSP页面中使用标签就等于调用某个对象的某个方法一样,例如:<c:if test="">,这就是在调用对象的方法一样。自定义标签其实就是自定义类一样!
定义标签处理类:必须是Tag或SimpleTag的实现类;
编写标签库描述符文件(TLD);
SimpleTag接口是JSP2.0中新给出的接口,用来简化自定义标签,所以现在我们基本上都是使用SimpleTag。
Tag是老的,传统的自定义标签时使用的接口,现在不建议使用它了。
2.SimpleTag接口介绍
SimpleTag接口内容如下:
void doTag():标签执行方法;
JspTag getParent():获取父标签;
void setParent(JspTag parent):设置父标签
void setJspContext(JspContext context):设置PageContext
void setJspBody(JspFragment jspBody):设置标签体对象;
请记住,万物皆对象!在JSP页面中的标签也是对象!你可以通过查看JSP的"真身"清楚的知道,所有标签都会变成对象的方法调用。
标签对应的类我们称之为"标签处理类"!
标签的生命周期:
1.当容器(Tomcat)第一次执行到某个标签时,会创建标签处理类的实例;
2.然后调用setJspContext(JspContext)方法,把当前JSP页面的pageContext对象传递给这个方法;
3.如果当前标签有父标签,那么使用父标签的标签处理类对象调用setParent(JspTag)方法;
4.如果标签有标签体,那么把标签体转换成JspFragment对象,然后调用setJspBody()方法;
5.每次执行标签时,都调用doTag()方法,它是标签处理方法。
四、案例
1.创建类HelloTag.java
public class HelloTag implements SimpleTag {
private JspTag parent;
private PageContext pageContext;
private JspFragment jspBody;
public void doTag() throws JspException, IOException {
pageContext.getOut().print("Hello Tag!!!");[获取out对象,输出Hello Tag!!!]
}
public void setParent(JspTag parent) {
this.parent = parent;
}
public JspTag getParent() {
return this.parent;
}
public void setJspContext(JspContext pc) {
this.pageContext = (PageContext) pc;
}
public void setJspBody(JspFragment jspBody) {
this.jspBody = jspBody;
}
}
2. 标签库描述文件(TLD)
标签库描述文件是用来描述当前标签库中的标签的!标签库描述文件的扩展名为tld,你可以把它放到WEB-INF下,这样就不会被客户端直接访问到了。
hello.tld
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd ">
<tlib-version>1.0</tlib-version>[指定当前标签库的版本]
<short-name>itcast</short-name>[指定当前标签库的简称,这个名称无所谓了,随便起。]
<uri>http://www.itcast.cn/tags</uri>[指定标签库的uri]
<tag>[部署一个标签!一个<tag>表示一个标签。]
<name>hello</name>[指定标签的名称]
<tag-class>cn.itcast.tag.HelloTag</tag-class>[指定标签处理类]
<body-content>empty</body-content>[指定标签体内容类型为空类型,即没有标签体。]
</tag>
</taglib>
3. 使用标签
在页面中使用标签分为两步:
使用taglib导入标签库;
使用标签;
<%@ taglib prefix="it" [指定标签库前缀]uri="/WEB-INF/hello.tld"[指定标签库的tld文件位置] %>
......
<it:hello/>
五、自定义标签进阶
1.继承SimpleTagSupport
继承SimpleTagSuppport要比实现SimpleTag接口方便太多了,现在你只需要重写doTag()方法,其他方法都已经被SimpleTagSuppport完成了。
public class HelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
this.getJspContext().getOut().write("<p>Hello SimpleTag!</p>")[向页面输出!注意,不能向页面输出<%%>东西!];
}
}
2.有标签体的标签
我们先来看看标签体内容的可选值:
<body-content>元素的可选值有:
empty:无标签体。
JSP[SimpleTag不能使用它!]:传统标签支持它,SimpleTag已经不再支持使用<body-content>JSP</body-content>。
标签体内容可以是任何东西:EL、JSTL、<%=%>、<%%>,以及html;
scriptless[它使用的最多!]:标签体内容不能是Java脚本,但可以是EL、JSTL等。在SimpleTag中,如果需要有标签体,那么就使用该选项;
tagdependent[没人会用!]:标签体内容不做运算,由标签处理类自行处理,无论标签体内容是EL、JSP、JSTL,都不会做运算。这个选项几乎没有人会使用!
自定义有标签体的标签需要:
获取标签体对象:JspFragment jspBody = getJspBody();;
把标签体内容输出到页面:jspBody.invoke(null);
tld中指定标签内容类型:scriptless。
public class HelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
PageContext pc = (PageContext) this.getJspContext();
HttpServletRequest req = (HttpServletRequest) pc.getRequest();
String s = req.getParameter("exec");
if(s != null && s.endsWith("true")) {
JspFragment body = this.getJspBody()[获取当前标签的标签体对象];
body.invoke[向页面输出标签体内容。](null);
}
}
}
<tag>
<name>hello</name>
<tag-class>cn.itcast.tags.HelloTag</tag-class>
<body-content>scriptless</body-content>[指定标签体内容为scriptless,即标签体内容可以是正常的html,也可以是EL或JSTL]
</tag>
<itcast:hello>
<h1>哈哈哈~</h1>
</itcast:hello>
3.不执行标签下面的页面内容
如果希望在执行了自定义标签后,不再执行JSP页面下面的东西,那么就需要在doTag()方法中使用SkipPageException。
public class SkipTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
this.getJspContext().getOut().print("<h1>只能看到我!</h1>");
throw new SkipPageException();[这个异常不会导致页面报错,但该标签下的内容就看不到了!]
}
}
<tag>
<name>skip</name>
<tag-class>cn.itcast.tags.SkipTag</tag-class>
<body-content>empty</body-content>
</tag>
<itcast:skip/>
<h1>看不见我!</h1>
4.带有属性的标签
一般标签都会带有属性,例如<c:if test="">,其中test就是一个boolean类型的属性。完成带有属性的标签需要:
在处理类中给出JavaBean属性(提供get/set方法);
在TLD中部属相关属性。
public class IfTag extends SimpleTagSupport {
private boolean test;
public boolean isTest() {
return test;
}
public void setTest[该方法会在doTag()之前被调用,传入属性值。](boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
if(test) {
this.getJspBody().invoke(null);
}[如果test为true,执行标签体内容,否则什么都不做。]
}
}
<tag>
<name>if</name>
<tag-class>cn.itcast.tag.IfTag</tag-class>
<body-content>scriptless</body-content>
<attribute>[声明属性]
<name>test</name>[属性名称为test]
<required>true</required>[为true表示属性是必须的,为false表示属性为可选的。]
<rtexprvalue>true</rtexprvalue>[为true表示属性值可以为EL或JSTL,否则表示只能是常量。]
</attribute>
</tag>
<%
pageContext.setAttribute("one", true);
pageContext.setAttribute("two", false);
%>
<it:if test="${one }">xixi</it:if>[可以看到xixi]
<it:if test="${two }">haha</it:if>[不会执行haha]
<it:if test="true">hehe</it:if>[可以看到hehe]
文章信息
- 本文作者:zhangxue
- 本文链接:https://lucksnow1989.github.io/article/2.JavaEE/4.jstl.html
- 版权声明:本文为本人原创文章,遵循 CC 4.0 BY-NC-SA版权协议,转载请附上原文出处链接和本声明。