學會怎樣使用Jsp 內置標簽、jstl標簽庫及自定義標簽


學習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>
復制代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM