javaweb:JSTL(JSP標準標籤庫)、自定義標籤開發
JSTL 簡介:
JSTL的全稱:
•JSP Standard Tag Library,JSP標準標籤庫
JSTL的作用:
•提供給 Java Web 開發人員一個標準通用的標籤函式庫
•和 EL 來取代傳統直接在頁面上嵌入 Java 程式(Scripting)的做法,以提高程式可讀性、維護性和方便性
JSTL的版本:
•JSTL的主要版本是1.0、1.1和1.2(區別不大)
•1.0版本EL表示式還沒有納入官方規範
•1.1和1.2版本EL表示式已經納入了官方規範
JSTL1.1下載相應的jar包:
JSTL的下載
•JSTL 主要由Apache
•http://tomcat.apache.org/taglibs/standard/
•容器必須支援Servlet 2.4 且JSP 2.0 以上版本
•JavaEE1.4
JSTL匯入jar包
•解壓縮後將lib 中的jstl.jar、standard.jar 複製到WEB應用程式的WEB-INF\lib 下
JSTL標籤庫:
核心標籤庫 (core) --- c(重點)
XML(x:操作xml的標籤庫)
SQL(sql標籤庫)
FMT(fmt:國際化標籤庫)
JSTL函式(EL函式) el
注意:EL表示式和JSTL標籤庫,操作都是域物件中的屬性和屬性的值
jstl1.2.jar 中包含的 5個標籤庫:
標籤 |
URI字首 |
字首 |
功能 |
Core |
http://java.sun.com/jsp/jstl/core |
<c:> |
核心標籤庫,基本操作 |
I18N |
http://java.sun.com/jsp/jstl/fmt |
<fmt:> |
格式化和國際化操作 |
XML |
http://java.sun.com/jsp/jstl/xml |
<x:> |
XML文件處理操作 |
SQL |
http://java.sun.com/jsp/jstl/sql |
<sql:> |
對資料庫的操作 |
Functions |
http://java.sun.com/jsp/jstl/functions |
<fn:> |
EL函式 |
JSTL快速入門:
l匯入jar包
•jstl.jar和standard.jar
l新建jsp的頁面
•在頁面中引入核心標籤庫
•<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
•
JSTL標籤庫關於匯入版本的問題
•http://java.sun.com/jsp/jstl/core 1.1或者1.2版本(使用該版本)
•http://java.sun.com/jstl/core 1.0版本(不支援EL表示式)
通用標籤 <c:out>、 <c:set>、 <c:remove>:
<c:out>標籤:
l輸出常量或者域範圍中的變數(value屬性,使用EL表示式)
l輸出預設值(default屬性)
l預設html標籤不轉義(escapeXml)
屬性名 |
是否支援EL |
屬性型別 |
屬 性 描 述 |
Value |
true |
Object |
指定要輸出的內容 |
escapeXml |
true |
Boolean |
指定是否將>、<、&、'、" 等特殊字元進行HTML編碼轉換後再進行輸出。預設值為true |
default |
true |
Object |
指定如果value屬性的值為null時所輸出的預設值 |
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h4>JSTL的方式</h4>
<%
int a =10;
request.setAttribute("num", a);
%>
<c:out value="num"></c:out>
<c:out value="${ num }"></c:out>
<!-- default 預設值 ${ num2 }如果num2沒有域屬性,輸出的是""-->
<c:out value="${ num2 }" default="北京"></c:out>
<c:out value="<a href='http://www.baidu.com'>百度</a>" escapeXml="false"/>
</body>
</html>
<c:set>標籤:
l向4個域中存入值。(var value scope屬性)
l設定Web域中的java.util.Map型別的屬性物件或JavaBean型別的屬性物件的屬性。 (target property value屬性)
屬性名 |
是否支援EL |
屬性型別 |
屬 性 描 述 |
value |
true |
Object |
用於指定屬性值 |
var |
false |
String |
用於指定要設定的Web域屬性的名稱 |
scope |
false |
String |
用於指定屬性所在的Web域 |
target |
true |
Object |
用於指定要設定屬性的物件,這個物件必須是JavaBean物件或java.util.Map物件 |
property |
true |
string |
用於指定當前要為物件設定的屬性名稱 |
<h4>JSTL的方式</h4>
<c:set var="username" value="meimei" scope="page"></c:set>
<c:out value="${ username }"></c:out>
<c:remove>標籤 :相當於request。removeAttribute(" x");
<c:remove>標籤用於刪除各種Web域中的屬性。
其語法格式如下:
<c:remove var="varName" scope="{page|request|session|application}"/>
<c:catch>標籤:
<c:catch>標籤用於捕獲巢狀在標籤體中的內容丟擲的異常,其語法格式如下:<c:catch [var="varName"]>nested actions</c:catch>
var屬性用於標識<c:catch>標籤捕獲的異常物件,它將儲存在page這個Web域中。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=gb2312" %>
<c:catch var="myex“ >
<%
10/0;
%>
</c:catch>
異常:<c:out value="${myex}" /> ${myex}<br />
異常 myex.getMessage:<c:out value="${myex.message}" /><br />
異常 myex.getCause:<c:out value="${myex.cause}" /><br />
異常 myex.getStackTrace:<c:out value="${myex.stackTrace}" />
<body>
<h4>JSTL的方式</h4>
<!--傳統方式 -->
<%
try{
}catch(Exception e){
}
%>
<c:catch var="e">
<%
int a = 10/0;
%>
</c:catch>
${ e.message }
</body>
<c:if>標籤:(沒有<c:else>標籤) 重點
<c:if test=“”>標籤可以構造簡單的“if-then”結構的條件表示式
屬性名 |
是否支援EL |
屬性型別 |
屬 性 描 述 |
test |
true |
boolean |
決定是否處理標籤體中的內容的條件表示式,test屬性必須出現 |
var |
false |
String |
用於指定將test屬性的執行結果儲存到某個Web域中的某個屬性的名稱(即test返回的結果儲存到var宣告的變數中,可以直接拿來使用) |
scope |
false |
String |
指定將test屬性的執行結果儲存到哪個Web域中(域的範圍) |
<body>
<h4>JSTL的方式</h4>
<c:set var="num" value="10" scope="page"></c:set>
<c:if test="${ num eq 10 }" var="i" scope="page">
num=10
</c:if>
<!-- 使用i的變數 -->
<c:if test="${ i }">
test=true
</c:if>
<myc:out>
EL表示式 JSTL
</myc:out>
</body>
<c:choose>標籤 : 重點
l<c:choose>標籤用於指定多個條件選擇的組合邊界,它必須與<c:when>和<c:otherwise>標籤一起使用。使用<c:choose>,<c:when>和<c:otherwise>三個標籤,可以構造類似 “if-else if-else” 的複雜條件判斷結構。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=gb2312" %>
<c:set value="${param.count}" var="count“ /> pageContext(count,2)
<c:choose>
<c:when test="${count == 0}">
對不起,沒有符合您要求的記錄。
</c:when>
<c:otherwise>
符合您要求的記錄共有${count}條.
</c:otherwise>
</c:choose>
<body>
<h4>JSTL的方式</h4>
<c:set var="num" value="10" scope="page"></c:set>
<c:choose>
<c:when test="${ num ge 10 }">
num>=10
</c:when>
<c:when test="${ num lt 10 }">
num<10
</c:when>
<c:otherwise>
其他
</c:otherwise>
</c:choose>
</body>
<c:forEach>標籤:
<c:forEach>標籤用於對一個集合物件中的元素進行迴圈迭代操作,或者按指定的次數重複迭代執行標籤體中的內容。
屬性名 |
是否支援EL |
屬性型別 |
屬 性 描 述 |
var |
false |
String |
指定將當前迭代到的元素儲存到page這個Web域中的屬性名稱(迴圈遍歷的數量儲存到var宣告變數中) |
varstatus |
false |
String |
記住用於儲存迭代資訊的物件 |
items |
true |
任何支援的型別 |
將要迭代的集合物件 |
begin |
true |
int |
如果指定items屬性,就從集合中的第begin個元素開始進行迭代,begin的索引值從0開始編號;如果沒有指定items屬性,就從begin指定的值開始迭代,直到end值時結束迭代 |
end |
true |
int |
參看begin屬性的描述 |
step |
true |
int |
指定迭代的步長,即迭代因子的迭代增量 |
例子 :
後臺程式:
package cn.itcast.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.domain.User;
/**
* 查詢的所有使用者的資訊
* @author Administrator
*/
public class UserServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 建立集合
List<User> uList = new ArrayList<User>();
// 把物件放入到集合 中
uList.add(new User("美美","123"));
uList.add(new User("小鳳","456"));
uList.add(new User("如花","789"));
// 把集合放入到request域中
request.setAttribute("uList", uList);
// 轉發到JSP頁面上
request.getRequestDispatcher("/jstl/foreach2.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
foreach.jsp
<body>
<h4>JSTL的方式</h4>
<%
List<String> list = new ArrayList<String>();
list.add("美美");
list.add("尹相傑");
list.add("高虎");
request.setAttribute("list", list);
%>
<h4>遍歷list集合和陣列方式是一樣的</h4>
<!-- for(String str : list){ } -->
<c:forEach var="str" items="${ list }">
${ str }
</c:forEach>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("aaa", "美美");
map.put("bbb", "小鳳");
map.put("ccc", "芙蓉");
request.setAttribute("map", map);
%>
<c:forEach var="entry" items="${ map }">
${ entry.key } -- ${ entry.value }
</c:forEach>
<h4>從1迴圈10</h4>
<c:forEach var="i" begin="1" end="10" step="1">
${ i }
</c:forEach>
<h1>從1加到10的和</h1>
<c:set var="sum" value="0" scope="page"></c:set>
<c:forEach var="i" begin="1" end="10" step="1">
<c:set var="sum" value="${ sum + i }" scope="page"></c:set>
</c:forEach>
${ sum }
<h4>遍歷10到100的偶數,每到第3個數,顯示紅色</h4>
<c:forEach var="i" begin="10" end="100" step="2" varStatus="status">
<c:choose>
<c:when test="${ status.first }">
<font color="green">${ i }</font>
</c:when>
<c:when test="${ status.count % 3 eq 0 }">
<font color="red">${ i }</font>
</c:when>
<c:otherwise>
${ i }
</c:otherwise>
</c:choose>
</c:forEach>
</body>
foreach.jsp :
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h4>JSTL的方式</h4>
<h4>可以獲取request域中的list集合</h4>
<c:forEach var="u" items="${ uList }" >
${ u.username }
${ u.password }
</c:forEach>
<h4>使用者資訊列表</h4>
<table border="1" width="60%" cellpadding="10">
<tr>
<th>序號</th>
<th>姓名</th>
<th>密碼</th>
<th>操作</th>
</tr>
<c:forEach var="user" items="${ uList }" varStatus="s">
<tr align="center">
<td>${ s.count }</td>
<td>${ user.username }</td>
<td>${ user.password }</td>
<td><a href="${ pageContext.request.contextPath }/deleteUser?username=${user.username}">刪除</a></td>
</tr>
</c:forEach>
</table>
</body>
</html>
<c:forEach>遍歷集合:
l遍歷陣列或者集合
•Var:代表遍歷的每一個元素
•Items:要迭代的集合物件
•獲取遍歷的內容:${xxx}
l遍歷Map集合
•Var:代表key與value的關係entry
•Items:要迭代的map集合
•獲取遍歷的內容:${xxx.key} ${xxx.value}
l遍歷物件集合
•Var:代表遍歷的每一個物件
•Items:要迭代的集合
•獲取遍歷的內容:${xxx.屬性}
<c:forEach>迭代資料:
l從1遍歷到10
•var 定義變數
•begin 從哪開始
•end 到哪結束
•step 迭代步長(相當於 x += step)
計算從1加到10的和
•定義變數sum,值為0
•通過forEach迴圈1到10,沒迴圈一次加到另一個變數中
•在迴圈中間定義變數,每次計算到該變數中
varStatus屬性:
<c:forTokens>(瞭解):
<c:forTokens>:
<c:forTokens
items=要切分的字串
delims=按著什麼格式切分
var=定義變數
[varStatus="varStatusName"]
[begin="begin"]
[end="end"]
[step="step"]>
//body內容
</c:forTokens>
URL相關標籤 <c:import>、<c:url>(重點)、<c:redirect> 、<c:param>:
<c:param>標籤 :
在JSP頁面進行URL的相關操作時,經常要在URL地址後面附加一些引數。<c:param>標籤可以巢狀在<c:import>、<c:url>或<c:redirect>標籤內,為這些標籤所使用的URL地址附加引數。
<c:param>標籤在為一個URL地址附加引數時,將自動對引數值進行URL編碼,例如,如果傳遞的引數值為“中國”,則將其轉換為“%d6%d0%b9%fa”後再附加到URL地址後面,這也就是使用<c:param>標籤的最大好處。
示例:<c:param name="name" value="value" />
<c:import> 標籤:
<c:url>標籤 :
<c:url>標籤用於在JSP頁面中構造一個URL地址,其主要目的是實現URL重寫。URL重寫就是將會話標識號以引數形式附加在URL地址後面
l使用value屬性預設會新增專案名稱。
屬性名 |
是否支援EL |
屬性型別 |
屬 性 描 述 |
value |
true |
String |
指定要構造的URL |
var |
false |
String |
指定將構造出的URL結果儲存到Web域中的屬性名稱 |
scope |
false |
String |
指定將構造出的URL結果儲存到哪個Web域中 |
<c:redirect>標籤:
l<c:redirect>標籤用於實現請求重定向
屬性名 |
是否支援EL |
屬性型別 |
屬 性 描 述 |
url |
true |
String |
指定要轉發或重定向到的目標資源的URL地址 |
context |
true |
String |
當要使用相對路徑重定向到同一個伺服器下的其他WEB應用程式中的資源時,context屬性指定其他WEB應用程式的名稱 |
自定義標籤簡介:
自定義標籤主要用於移除Jsp頁面中的java程式碼,提高程式碼的複用性。
使用自定義標籤移除jsp頁面中的java程式碼,只需要完成以下兩個步驟:
•編寫一個實現Tag介面的Java類(標籤處理器類)
•編寫標籤庫描述符(tld)檔案,在tld檔案中對標籤處理器類描述成一個標籤
第一步:
建一個java類,在裡面自定義方法:
package cn.itcast.el;
/**
* 後臺的自定義EL函式
* @author Administrator
*
*/
public class ElDemo {
/**
* say hello方法
* @param str
* @return
*/
public static String sayHello(String str){
return "hello "+str;
}
}
第二步:
在WEB-INF目錄下建立一個資料夾,並在資料夾中建立一個 myc.tid檔案,這是一個配置檔案,在此檔案中完成配置
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" 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">
<tlib-version>1.0</tlib-version>
<short-name>myc</short-name>
<uri>http://www.itcast.cn/0108/myc</uri>
<!-- 配置自定義標籤 -->
<tag>
<!-- 配置標籤名稱 -->
<name>print</name>
<!-- 標籤使用的類 -->
<tag-class>cn.itcast.jstl.JstlDemo1</tag-class>
<!-- 配置標籤主體 -->
<body-content>empty</body-content>
</tag>
<!-- 配置自定義標籤 -->
<tag>
<!-- 配置標籤名稱 -->
<name>out</name>
<!-- 標籤使用的類 -->
<tag-class>cn.itcast.jstl.JstlDemo2</tag-class>
<!-- 配置標籤主體 -->
<body-content>scriptless</body-content>
</tag>
<!-- 配置自定義標籤 -->
<tag>
<!-- 配置標籤名稱 -->
<name>if</name>
<!-- 標籤使用的類 -->
<tag-class>cn.itcast.jstl.JstlDemo3</tag-class>
<!-- 配置標籤主體 -->
<body-content>scriptless</body-content>
<!-- 配置屬性 -->
<attribute>
<!-- 配置資料名稱 -->
<name>test</name>
<!-- 屬性是否是必須出現的 -->
<required>true</required>
<!-- 支援EL表示式 -->
<rtexprvalue>true</rtexprvalue>
<!-- 屬性的型別 -->
<type>boolean</type>
</attribute>
</tag>
</taglib>
第三步:
在jsp中引用自己定義的EL函式:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 引入自己的EL函式 -->
<%@ taglib prefix="myfn" uri="http://www.itcast.cn/0108/myfn" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h4>使用自己編寫EL函式</h4>
${ myfn:sayHi("小鳳") }
</body>
</html>
•參考tomcat中的examples 專案中jsp 部分
簡單標籤:
l由於傳統標籤使用三個標籤介面來完成不同的功能,顯得過於繁瑣,不利於標籤技術的推廣, SUN公司為降低標籤技術的學習難度,在JSP 2.0中定義了一個更為簡單、便於編寫和呼叫的SimpleTag介面來實現標籤的功能。實現SimpleTag介面的標籤通常稱為簡單標籤。簡單標籤共定義了5個方法:
•setJspContext方法
•setParent和getParent方法
•setJspBody方法
•doTag方法
SimpleTag方法介紹:閱讀API
lsetJspContext方法
•用於把JSP頁面的pageContext物件傳遞給標籤處理器物件
lsetParent方法
•用於把父標籤處理器物件傳遞給當前標籤處理器物件
lgetParent方法
•用於獲得當前標籤的父標籤處理器物件
lsetJspBody方法
•用於把代表標籤體的JspFragment物件傳遞給標籤處理器物件
ldoTag方法
•用於完成所有的標籤邏輯,包括輸出、迭代、修改標籤體內容等。在doTag方法中可以丟擲javax.servlet.jsp.SkipPageException異常,用於通知WEB容器不再執行JSP頁面中位於結束標記後面的內容,這等效於在傳統標籤的doEndTag方法中返回Tag.SKIP_PAGE常量的情況。
SimpleTag介面方法的執行順序:
l當web容器開始執行標籤時,會呼叫如下方法完成標籤的初始化
•WEB容器呼叫標籤處理器物件的setJspContext方法,將代表JSP頁面的pageContext物件傳遞給標籤處理器物件。
•WEB容器呼叫標籤處理器物件的setParent方法,將父標籤處理器物件傳遞給這個標籤處理器物件。注意,只有在標籤存在父標籤的情況下,WEB容器才會呼叫這個方法。
•如果呼叫標籤時設定了屬性,容器將呼叫每個屬性對應的setter方法把屬性值傳遞給標籤處理器物件。如果標籤的屬性值是EL表示式或指令碼表示式,則WEB容器首先計算表示式的值,然後把值傳遞給標籤處理器物件。
•如果簡單標籤有標籤體,容器將呼叫setJspBody方法把代表標籤體的JspFragment物件傳遞進來。
l執行標籤時:
•容器呼叫標籤處理器的doTag()方法,開發人員在方法體內通過操作JspFragment物件,就可以實現是否執行、迭代、修改標籤體的目的。
JspFragment類:
ljavax.servlet.jsp.tagext.JspFragment類是在JSP2.0中定義的,它的例項物件代表JSP頁面中的一段符合JSP語法規範的JSP片段,這段JSP片段中不能包含JSP指令碼元素。
lWEB容器在處理簡單標籤的標籤體時,會把標籤體內容用一個JspFragment物件表示,並呼叫標籤處理器物件的setJspBody方法把JspFragment物件傳遞給標籤處理器物件。JspFragment類中只定義了兩個方法,如下所示:
lgetJspContext方法
•用於返回代表呼叫頁面的JspContext物件. ---- pageContext
lpublic abstract void invoke(java.io.Writer out) -- 輸出標籤體內容
•用於執行JspFragment物件所代表的JSP程式碼片段
•引數out用於指定將JspFragment物件的執行結果寫入到哪個輸出流物件中,如果傳遞給引數out的值為null,則將執行結果寫入到JspContext.getOut()方法返回的輸出流物件中。(簡而言之,可以理解為寫給瀏覽器)
invoke方法詳解 :
lJspFragment.invoke方法是JspFragment最重要的方法,利用這個方法可以控制是否執行和輸出標籤體的內容、是否迭代執行標籤體的內容或對標籤體的執行結果進行修改後再輸出。例如:
•在標籤處理器中如果沒有呼叫JspFragment.invoke方法,其結果就相當於忽略標籤體內容;
•在標籤處理器中重複呼叫JspFragment.invoke方法,則標籤體內容將會被重複執行;
•若想在標籤處理器中修改標籤體內容,只需在呼叫invoke方法時指定一個可取出結果資料的輸出流物件(例如StringWriter),讓標籤體的執行結果輸出到該輸出流物件中,然後從該輸出流物件中取出資料進行修改後再輸出到目標裝置,即可達到修改標籤體的目的。
例:控制標籤後的jsp頁面是否執行
ldoTag
•throw new SkipPageException()
•
lTld配置
• <tag>
• <name>demo2</name>
• <tag-class>simple.MyTag2</tag-class>
• <body-content>empty</body-content>
• </tag>
自定義標籤入門:
l需求:自定義標籤<myc:print>在頁面中輸出hello
•編寫標籤類
•編寫一個類,繼承SimpleTagSuppot類。
•重寫兩個方法,doTag()和setJspContext(JspContext pc)
•通JspContext物件可以獲取out物件向外輸出內容
•
•提供tld檔案進行配置
•通過<tag>標籤配置自定義標籤
•配置標籤名稱<name>print</name>
•配置標籤的類<tag-class>xxx.xxx.xxx</tag-class>
•配置標籤體的內容<body-content>empty</body-content>
•在JSP的頁面中引入該標籤庫
自定義帶有標籤體的標籤:
l需求:自定義標籤<myc:out>在頁面中輸出內容
•編寫標籤類
•編寫一個類,繼承SimpleTagSuppot類。