1. 程式人生 > >jsp自定義標簽

jsp自定義標簽

ref otherwise array type while entryset 利用 inf something

概念

自定義標簽是用戶定義的JSP語言元素。當JSP頁面包含一個自定義標簽時將被轉化為servlet,標簽轉化為對被 稱為tag handler的對象的操作,即當servlet執行時Web container調用那些操作。

JSP標簽擴展可以讓你創建新的標簽並且可以直接插入到一個JSP頁面。 JSP 2.0規範中引入Simple Tag Handlers來編寫這些自定義標記。

你可以繼承SimpleTagSupport類並重寫的doTag()方法來開發一個最簡單的自定義標簽。

SimpleTagSupport類的API

見文檔 http://tomcat.apache.org/tomcat-5.5-doc/jspapi/

public class SimpleTagSupportextends java.lang.Objectimplements SimpleTag

A base class for defining tag handlers implementing SimpleTag.

The SimpleTagSupport class is a utility class intended to be used as the base class for new simple tag handlers. The SimpleTagSupport class implements the SimpleTag interface and adds additional convenience methods including getter methods for the properties in SimpleTag.

Since: 2.0
Method Summary
void doTag()
Default processing of the tag does nothing.
static JspTag findAncestorWithClass(JspTag from, java.lang.Class klass)
Find the instance of a given class type that is closest to a given instance.
protected JspFragment getJspBody()
Returns the body passed in by the container via setJspBody.
protected JspContext getJspContext()
Returns the page context passed in by the container via setJspContext.
JspTag getParent()
Returns the parent of this tag, for collaboration purposes.
void setJspBody(JspFragment jspBody)
Stores the provided JspFragment.
void setJspContext(JspContext pc)
Stores the provided JSP context in the private jspContext field.
void setParent(JspTag parent)
Sets the parent of this tag, for collaboration purposes.

從其方法中可以看出,只要繼承了SimpleTagSupport就可以得到pageContext(getJspContext),標簽體(getJspBody)。並且web服務器在處理自定義標簽的時候,方法調用順序如下:

           Web服務器----->jsp------>實例化標簽處理器
           ------>調用setJspContext把pageContext傳遞給標簽處理器
           ------>調用setParent把父標簽傳遞進去,沒有則傳null
           ------>調用setJspBody傳遞封裝標簽體的JspFragment
           ------>執行自定義標簽,調用doTag
           ------>系統自動處理銷毀標簽處理器,結束調用

從上面調用順序看,我們只需要重寫doTag方法實現我們的業務處理就可以了。

自定義標簽的步驟

在開發中,只要按以下步驟一步步來,就不會出錯。

第一步 創建標簽,格式如下

//不帶標簽體的標簽
<ex:tagname>
</ex:tagname>
--------------------
<ex:tagname/>
--------------------
//帶標簽體的
<ex:tagname>
      helloworld!
</ex:tagname>
--------------------
//帶屬性的
<ex:tagname count="3">
輸出3次標簽體
</ex:tagname>

第二步,創建標簽實體類,即在web應用下的src目錄下創建一個繼承SimpleTagSupport類的標簽類,在doTag方法裏進行邏輯處理

public class HelloTag extends SimpleTagSupport {

  public void doTag() throws JspException, IOException {
    JspWriter out = getJspContext().getOut();//取到jsp中的printWriter
    out.println("Hello Custom Tag!");
  }
}

第三步,在tld文件中對標簽進行聲明,並將文件命名為ex.tld並放在WEB-INFO目錄下,在jsp文件中進行引用時,最好將prefix寫成與tld文件名一樣,便於查找

<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>2.0</jsp-version>
  <short-name>Example TLD</short-name>
<uri>http://www.extag.cn</uri> //導入標簽的時候需填寫這個uri
<tag> <name>Hello</name> <tag-class>ex.package.HelloTag</tag-class> //標簽處理類的全名 <body-content>empty</body-content> //表示標簽體為空 </tag> </taglib>

第四步,在jsp文件中導入並使用

<%@ taglib prefix="ex" uri="http://www.extag.cn"%>
<html>
  <head>
    <title>A sample custom tag</title>
  </head>
  <body>
    <ex:Hello/>
  </body>
</html>

幾個常見例子

在例子中只列出doTag中的關鍵代碼 及tld文件中的配置

1、控制標簽體是否執行或顯示,如果不顯示,則在doTag中空實現

public void doTag () throws JspException,IOException{
         JspFragment jf = this.getJspBody();
         jf.invoke(this.getJspContext().getOut());
}

<tag>
         <name>ex1</name>
         <tag-class>package.ex1</tag-class>
         <body-content>scriptless</body-content>  
          //2.0版本sun公司新規範,不允許jsp中寫java代碼, 之前的寫法:<body-content>JSP</body-content>
</tag>

2、修改標簽體

public void doTag () throws JspException,IOException{
         JspFragment jf = this.getJspBody();
StringWriter sw = new StringWriter();
jf.invoke(sw);
String content = sw.toString;
//todo something for modify content
this.getJspContext().getOut().write(content);//將修改後的標簽體輸出 }

3、控制標簽余下的jsp不執行

這裏列出doTag方法的說明

public void doTag()
           throws JspException,
                  java.io.IOException
Throws:
JspException - Subclasses can throw JspException to indicate an error occurred while processing this tag.
SkipPageException - If the page that (either directly or indirectly) invoked this tag is to cease evaluation. A Simple Tag Handler generated from a tag file must throw this exception if an invoked Classic Tag Handler returned SKIP_PAGE or if an invoked Simple Tag Handler threw SkipPageException or if an invoked Jsp Fragment threw a SkipPageException.
java.io.IOException - Subclasses can throw IOException if there was an error writing to the output stream
要想不執行標簽後的jsp內容,只需要拋出SkipPageException即可。
public void doTag () throws JspException,IOException{
       throw new SkipPageException();
}

3、帶屬性的標簽

<ex:exam3 count="3">
     body
</ex:exam3>

與之前幾種不同的是,需要在標簽處理類中定義接收屬性值的變量,並實現setter方法,setter方法在接收 屬性時支持8種基本類型的自動轉換, 像date類的 String d="1983-11-30", 如在標簽處理類中用Date變量接收,由於不支持非基本類型的轉換,在執行標簽時會報錯。

這個例子要實現的功能是重復輸出標簽體,代碼如下

public class Exam3 extends SimpleTagSupport{
        private int count;
        public void setCount(int count){
                this.count = count;
        }

        public void doTag () throws JspException,IOException{
               JspFragment jf = this.getJspBody();
               for (int i=0; i<count; i++){
                      jf.invoke(null);// null時默認輸出標簽體
               }
         }
}
<tag>
         <name>exam3</name>
         <tag-class>package.ex3</tag-class>
         <body-content>scriptless</body-content>  
         <attribute> 
                 <name>count</name>
                 <required>true</required>  //表示 為必填屬性
                 //為true時,表示該屬性同時支持字串賦值和el表達式賦值,count="${user.count}"
                 <rtexprvalue>true</rtexprvalue>
         </attribute>
</tag>

4、防盜鏈標簽

原理:假如有主頁A, 目標頁面B, A上面有鏈接可點擊來到頁面B,這時你的朋友覺得頁面B很有意思,於是把頁面B通過QQ或其他方式分享給你,你點開頁面後,奇怪的是發現並不是頁面B,而是來到了充滿了廣告的主頁面A,這就是防盜鏈技術。