學習jsp不得不學習jsp标簽,一般來說,對于一個jsp開發者,可以了解為jsp頁面中出現的java代碼越少,對jsp的掌握就越好,而替換掉java代碼的重要方式就是使用jsp标簽。
jsp标簽的分類:
1)内置标簽(動作标簽): 不需要在jsp頁面導入标簽
2)jstl标簽: 需要在jsp頁面中導入标簽
3)自定義标簽 : 開發者自行定義,需要在jsp頁面導入标簽
1、内置标簽(動作标簽):
<jsp:forward />轉發标簽:
文法:<jsp:forward page="/MyJsp001.jsp"></jsp:forward>
相當于java代碼:request.getRequestDispatcher("/MyJsp001.jsp?name=jxf").forward(request, response);
注意:但是java代碼的轉發可以通過url帶參數的方式進行傳遞參數,而轉發标簽需要借助于下面的<jsp:param>标簽實作參數傳遞
<jsp:pararm/>參數标簽:
文法: <jsp:param value="jxf" name="name"/> <%-- 傳遞一個名為name,值為jxf的參數,參數一般作為其他标簽的子标簽使用--%>
結合<jsp:forward>标簽用法:
<jsp:forward page="/MyJsp001.jsp">
<jsp:param value="jxf" name="name"/>
</jsp:forward>
<jsp:include/>包含标簽:
文法:
<jsp:include page="/MyJsp001.jsp">
<jsp:param value="jxf" name="name"/><%--可以将參數傳遞給包含進來的頁面--%>
</jsp:include>
jsp中還有一個包含指令,也是将一個頁面包含另外的頁面
他們之間的差別:
1、首先是文法不同
<jsp:include page="/MyJsp001.jsp">
<%@inclue file="被包含的頁面"%>
2、<jsp:include>可以傳遞參數,<%@inclue%>不可以
3、<jsp:include>:包含頁面與被包含頁面分别編譯為兩個java源檔案,在運作時引用
<%@inclue%>:包含頁面與被包含頁面合并編譯為一個java源檔案
2、jstl标簽:
JSTL (java standard tag libarary - java标準标簽庫)
jstl标簽的類型:
核心标簽庫 (c标簽庫)//這裡主要介紹c标簽庫,因為用的真的很多
國際化标簽(fmt标簽庫)
EL函數庫(fn函數庫)
xml标簽庫(x标簽庫)//一般不用該庫,這屬于資料操作,而資料操作應于dao層中,jsp頁面主要用于展示資料
sql标簽庫(sql标簽庫)//與xml标簽庫類似,不應在jsp頁面中操作資料(當然他們是可以在jsp頁面寫)
使用jstl标簽庫使用前提(此處以c标簽庫為例):
1、導入jstl支援包:jstl-1.2.jar(如果用MyEclipse建立項目時候選擇java EE5.0,則不需要導包,工程中已經包含)
2、在頁面中使用Taglib指令導入标簽庫
<%--uri:tld檔案中的uri名稱,prefix:标簽字首--%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
uri和prefix怎樣寫?以标簽庫的為例:
工程名->Java EE 5 Libraries->jstl-1.2.jar->META-INF-c.tld

c标簽庫的主要标簽:
<c:set>标簽:用于儲存資料到域對象中
<%--var為屬性名 value為屬性值 scope為儲存屬性到那個域對象,預設為page域 --%>
<%--相當于java代碼<%pageContext.setAttribute("name", "jxf") --%>
<c:set var="name" value="jxf" scope="page"></c:set>
${name}<%--EL表達式輸出page域中的name屬性值--%>
<c:out>标簽:顯示資料
<%--value:輸出到浏覽器的值,${name}EL表達式取出域對象屬性值為name的值,
default:當value值為null時顯示的預設值,
escapeXml:表示是否轉義為xml格式(也可以了解為普通文本格式),true表示轉義,預設false --%>
<c:out value="${name}" default="<h1>标題h1<h1>" escapeXml="false"></c:out>
<c:if>标簽:但條件判斷
<%--test支援EL表達式 --%>
<c:if test="${true}">
條件成立!
</c:if>
<c:choose>+<c:when>+<c:otherwise>标簽:多條件判斷
<%--相當于if else結構,當有一條件滿足後其他條件都不滿足,證:此執行個體隻輸出 10>5--%>
<c:choose>
<c:when test="${10>5}">
10>5<br />
</c:when>
<c:when test="${6>2}">
6>2<br />
</c:when>
<c:otherwise>
條件都不成立
</c:otherwise>
</c:choose>
<c:forEach>标簽:周遊
<%--
begin : 從哪個元素開始周遊,預設從0開始
end : 到哪個元素結束。預設到最後一個元素
step : 步長,預設1
items : 需要周遊的資料(集合)
var : 每個元素的名稱
varStatus: 目前正在周遊元素的狀态對象。(count屬性:目前位置,從1開始)
--%>
<%
//Student{
// public String name;
// public int age;
// public Student(String Name,int Age){
// this.name = Name;
// this.age = age;
// }
//}
//List資料準備
List<Student> list = new ArrayList<Student>();
list.add(new Student("name001",18));
list.add(new Student("name002",19));
list.add(new Student("name003",20));
pageContext.setAttribute("list",list);//放入域中
//Map資料準備
Map<String,Student> map = new HashMap<String,Student>();
map.put("001",new Student("name001",18));
map.put("002",new Student("name002",19));
map.put("003",new Student("name003",20));
pageContext.setAttribute("map",map);//放入域中
//array資料準備
Student[] array = new Student[]{
new Student("name001",18),
new Student("name002",19),
new Student("name003",20)};
pageContext.setAttribute("array",array);//放入域中
%>
<%--周遊list --%>
<c:forEach var="student" begin="0" end="2" items="${list}" step="1" varStatus="varSta">
name:${student.name}---age:${student.age}<br/>
</c:forEach>
<%--周遊map --%>
<c:forEach var="student" begin="0" end="2" items="${map}" step="1" varStatus="varSta">
key:${student.key}---name:${student.value.name}---age:${student.value.age}<br/>
</c:forEach>
<%--周遊array --%>
<c:forEach var="student" begin="0" end="2" items="${array}" step="1" varStatus="varSta">
name:${student.name}---age:${student.age}<br/>
</c:forEach>
<%--一般周遊集合或者數組都是全部周遊,是以隻寫2個屬性var和items,其他取預設值 --%>
<c:forEach var="student" items="${array}">
name:${student.name}---age:${student.age}<br/>
</c:forEach>
<c:forTokens>标簽:切割字元串
<%--
切割字元串,相當于split函數
var:切割出來的每一部分字元串
items:要切割的字元串
delims:分割的字元,若内容為字元串,則這個字元串的每個字元都會當作一個分割的字元
如:items="a-b-c=d=e" dilims="-=",分割的結果為 a,b,c,d,e
--%>
<%
//資料準備
String str = "a-b-c=d=e";
pageContext.setAttribute("str", str);
%>
<c:forTokens var="item" items="${str}" delims="-=">
${item}<br />
</c:forTokens>
3、自定義标簽:
當JSTL标簽庫已經無法滿足我們的需求時候,就需要自己開發自定義标簽,來滿足我們的需求,自定義标簽實際上是一個普通的java類,繼承SimpleTagSupport類。
在介紹自定義标簽之前,先介紹SimpleTagSupport類:
SimpleTagSupport類繼承自SimpleTag接口,而SimpleTag接口主要有以下4個方法,也可将這四個方法了解為标簽處理器類的生命周期:
1 public interface SimpleTag extends JspTag {
2
3 /**
4 * 執行标簽時調用的方法,一定會調用
5 */
6 public void doTag() throws javax.servlet.jsp.JspException, java.io.IOException;
7
8 /**
9 * 設定父标簽對象,傳入父标簽對象,當标簽存在父标簽時會調用
10 */
11 public void setParent( JspTag parent );
12
13 /**
14 * 設定JspContext對象,其實他真實傳入的是其子類PageContext
15 */
16 public void setJspContext( JspContext pc );
17
18 /**
19 * 設定标簽體内容。标簽體内容封裝到JspFragment對象 中,然後傳入JspFragment對象
20 */
21 public void setJspBody( JspFragment jspBody );
22
23 }
SimpleTagSupport類在其基礎上封裝出了3個方法,友善自定義标簽類編寫,該方法實作也比較簡單,無非就是内部維護一個變量,通過set方法将其指派,再傳回該對象,這樣繼承SimpleTagSupport拿到如PageContext對象就直接調用getJspContext()即可。
1 /*SimpleTagSupport 類的一部分*/
2 public class SimpleTagSupport implements SimpleTag
3 {
4 /** Reference to the enclosing tag. */
5 private JspTag parentTag;
6
7 /** The JSP context for the upcoming tag invocation. */
8 private JspContext jspContext;
9
10 /** The body of the tag. */
11 private JspFragment jspBody;
12
13 public void setParent( JspTag parent ) {
14 this.parentTag = parent;
15 }
16
17 public JspTag getParent() {
18 return this.parentTag;
19 }
20
21 public void setJspContext( JspContext pc ) {
22 this.jspContext = pc;
23 }
24
25 protected JspContext getJspContext() {
26 return this.jspContext;
27 }
28
29 public void setJspBody( JspFragment jspBody ) {
30 this.jspBody = jspBody;
31 }
32
33 protected JspFragment getJspBody() {
34 return this.jspBody;
35 }
36 }
編寫自定義标簽的步驟:
以寫一個自定義标簽為例:功能:向浏覽器輸出一句話“酒香逢 部落格園歡迎您”
1)編寫一個普通的java類(OutInfo.java),繼承SimpleTagSupport類,并重寫doTag方法。(jsp檔案最後編譯為java檔案,檢視該java檔案可知_jspService方法中,會建立标簽類OutInfo對象,并執行doTag方法。編譯後原檔案路徑:如D:\Program Files\Tomcat\apache-tomcat-6.0.39\work\Catalina\localhost\Tag\org\apache\jsp\xxx.java)
1 /*
2 * OutInfo.java
3 */
4 public class OutInfo extends SimpleTagSupport {
5
6 @Override
7 public void doTag() throws JspException, IOException {
8 PageContext pageContext = (PageContext)getJspContext();
9 pageContext.getOut().write("酒香逢 部落格園歡迎您");
10 }
11 }
2)在web項目的WEB-INF目錄下建立tld檔案(jxf.tld),這個tld檔案為标簽庫的聲明檔案,并配置好相應的資訊。(可以參考核心标簽庫的tld檔案,如:項目/Java EE 5 Libraries/jstl-1.2jar/META-INF/c.tld)
1 <?xml version="1.0" encoding="UTF-8" ?>
2
3 <taglib xmlns="http://java.sun.com/xml/ns/javaee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
6 version="2.1">
7
8 <description>JSTL 1.1 core library</description>
9 <display-name>JSTL core</display-name>
10 <tlib-version>1.1</tlib-version>
11 <!--标簽庫字首 taglib指令中的prefix屬性 -->
12 <short-name>jxf</short-name>
13 <!--tld檔案的唯一标記 taglib指令中的uri屬性 -->
14 <uri>http://jxf.tag</uri>
15
16 <tag>
17 <description>
18 這是自定義标簽的描述資訊,可以在MyEclipse中有提示
19 </description>
20 <!-- 标簽名 -->
21 <name>outInfo</name>
22 <!-- 标簽類的完名 -->
23 <tag-class>jxf.OutInfo</tag-class>
24 <body-content>scriptless</body-content>
25 <!-- <attribute>
26 <description>
27 這是屬性的描述資訊
28 </description>
29 <name>var</name>
30 <required>false</required>
31 <rtexprvalue>false</rtexprvalue>
32 </attribute> -->
33 </tag>
34
35 </taglib>
3)在jsp頁面的頭部導入自定義标簽庫
<%@taglib uri="http://jxf.tag" prefix="jxf" %>
4)在jsp中使用自定義标簽
<jxf:outInfo></jxf:outInfo>
5)jsp頁面
1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
2 <%@taglib uri="http://jxf.tag" prefix="jxf" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>自定義标簽</title>
7 </head>
8 <body>
9 <jxf:outInfo></jxf:outInfo>
10 </body>
11 </html>
自定義标簽能夠做的:
1)控制标簽體内容輸出
1 /*
2 * 1)輸出标簽題内容
3 */
4 JspFragment jspBody = getJspBody();
5 //方法:invoke(java.io.Writer out)
6 //當參數為null時等價于 jspBody.invoke(getJspContext().getOut());
7 jspBody.invoke(null);
2)控制标簽餘下内容輸出
1 /*
2 * 2)控制标簽體餘下内容是否輸出
3 * 抛出一個SkipPageException異常後,标簽體餘下内容輸出
4 */
5 throw new SkipPageException();
3)改變标簽體内容
1 /*
2 * 3)改變标簽體内容并輸出到浏覽器
3 */
4 //擷取到标簽體内容,并儲存到自定義的款沖字元流中
5 StringWriter sw = new StringWriter();
6 //jspBodyString得到的即是标簽體的内容
7 String jspBodyString = sw.toString();
8 jspBodyString = "簡單将字元串的值改變掉";
9 getJspContext().getOut().write(jspBodyString);//輸出到浏覽器
4)帶屬性的标簽(以模仿c标簽的<c:choose>+<c:when>+<c:otherwise>标簽為例)
編寫3個自定義标簽處理器類 ChooseTag.java、 When.java、 Otherwise.jave
1 /*
2 * ChooseTag.java
3 */
4 public class ChooseTag extends SimpleTagSupport {
5 private boolean flag = false;
6
7 public boolean isFlag() {
8 return flag;
9 }
10
11 public void setFlag(boolean flag) {
12 this.flag = flag;
13 }
14 @Override
15 public void doTag() throws JspException, IOException {
16 getJspBody().invoke(null);
17 }
18 }
/*
* WhenTag.java
*/
public class WhenTag extends SimpleTagSupport {
private boolean test;
//tld檔案中的屬性必須要有對應的set方法,否則報錯
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
ChooseTag parent = (ChooseTag)getParent();
if(!parent.isFlag()){
if(test){
parent.setFlag(true);
getJspBody().invoke(null);
}
}
}
}
1 /*
2 * OtherwiseTag.java
3 */
4 public class OtherwiseTag extends SimpleTagSupport {
5 @Override
6 public void doTag() throws JspException, IOException {
7 ChooseTag parent = (ChooseTag)getParent();
8 if(!parent.isFlag()){
9 getJspBody().invoke(null);
10 }
11 }
12 }
tld檔案
1 <?xml version="1.0" encoding="UTF-8" ?>
2
3 <taglib xmlns="http://java.sun.com/xml/ns/javaee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
6 version="2.1">
7
8 <description>JSTL 1.1 core library</description>
9 <display-name>JSTL core</display-name>
10 <tlib-version>1.1</tlib-version>
11 <!--标簽庫字首 taglib指令中的prefix屬性 -->
12 <short-name>jxf</short-name>
13 <!--tld檔案的唯一标記 taglib指令中的uri屬性 -->
14 <uri>http://jxf.tag</uri>
15
16 <tag>
17 <name>chooseTag</name>
18 <tag-class>jxf.ChooseTag</tag-class>
19 <body-content>scriptless</body-content>
20 </tag>
21 <tag>
22 <description>
23 自定義的when标簽
24 </description>
25 <name>whenTag</name>
26 <tag-class>jxf.WhenTag</tag-class>
27 <body-content>scriptless</body-content>
28 <attribute>
29 <description>
30 when标簽屬性test
31 </description>
32 <!-- 标簽處理器類中的必須要有對應的set方法,否則會報錯,如此時對應的标簽處理器類中應有getTest()方法。 -->
33 <name>test</name>
34 <!-- 該屬性是否是必須的 ,true為必須的,false為非必須的-->
35 <required>true</required>
36 <!-- 該屬性是否支援EL表達式 true支援,false不支援 -->
37 <rtexprvalue>true</rtexprvalue>
38 </attribute>
39 </tag>
40 <tag>
41 <name>otherwiseTag</name>
42 <tag-class>jxf.OtherwiseTag</tag-class>
43 <body-content>scriptless</body-content>
44 </tag>
45 </taglib>
jsp代碼
1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
2 <%@taglib uri="http://jxf.tag" prefix="jxf"%>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>模仿c标簽庫的choose,when,otherwise</title>
7 </head>
8 <body>
9 <jxf:demoTag>标簽體内容</jxf:demoTag>
10 标簽體餘下内容
11 <br />
12 <jxf:chooseTag>
13 <jxf:whenTag test="${4>5}">
14 4>5是不輸出的
15 </jxf:whenTag>
16 <jxf:whenTag test="${10>5}">
17 10>5是成立的
18 </jxf:whenTag>
19 <jxf:whenTag test="${9>5}">
20 9>5是成立的,但是不輸出
21 </jxf:whenTag>
22 <jxf:otherwiseTag>
23 當條件都不成立時候輸出(由于第二個提條件成立,故不應輸出)
24 </jxf:otherwiseTag>
25 </jxf:chooseTag>
26 </body>
27 </html>