學習jsp不得不學習jsp標簽,一般來說,對於一個jsp開發者,可以理解為jsp頁面中出現的java代碼越少,對jsp的掌握就越好,而替換掉java代碼的重要方式就是使用jsp標簽。
1)內置標簽(動作標簽): 不需要在jsp頁面導入標簽
2)jstl標簽: 需要在jsp頁面中導入標簽
3)自定義標簽 : 開發者自行定義,需要在jsp頁面導入標簽
<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源文件
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>
當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>

