JSP自定義標籤——傳統標籤

  同JSP標籤同樣,自定義標籤主要用於移除JSP頁面中的Java代碼,能夠看到咱們在JSP中實際上是禁止使用Java腳本的,任何要想經過Java代碼實現的功能都必須以標籤形式來處理,可使用JSP標籤,JSTL標籤,EL函數,或者自定義標籤。html

  自定義標籤分爲傳統標籤和簡單標籤,簡單標籤是Sun公司爲減低自定義標籤技術的學習難度而定義的,對於簡單標籤請看下一篇博客。本文先來學習傳統自定義標籤。java

  使用傳統自定義標籤須要知足如下兩個步驟:web

  ① 編寫一個實現Tag接口(實際上咱們更常的是繼承Tag接口的實現類從而免於覆寫全部的方法)的Java類,這個Java類也稱爲標籤處理器類。瀏覽器

  ② 編寫標籤的TLD文件,用於指定標籤的URI和對標籤的聲明描述,這一點和EL函數時同樣的,TLD文件必須放置在web應用下的【WEB-INF】文件中,能夠是除【classes】和【lib】目錄之外的任何子目錄中。TLD文件的模板能夠從【Tomcat】--->【webapps】--->【examples】--->【WEB-INF】--->【jsp2】中有一個「jsp2-example-taglib.tld」文件複製首尾和其中的<Tag>標籤。服務器

  注:在TLD文件中咱們使用<tag>標籤來對每個自定義標籤的Java類進行描述,其中每一個<tag>標籤下還須要指定<body-content>的值,這個是描述標籤體的類型:session

  對於傳統標籤使用:「EMPTY」(表明標籤沒有標籤體)或「JSP」(表明標籤有標籤體)。app

 

  以上的步驟總體相似於咱們自定義EL函數,而不一樣的是這裏的Java類須要繼承特定的JSP的API中提供的類並覆蓋其中特定的方法。webapp

 

  咱們先看一看Tag類的API,注意,這是JSP技術,請看JSP的API:jsp

  

  

  從上面能夠看到Tag是一個接口,若是咱們直接繼承Tag接口的話,那就得覆寫這六個方法,那就顯得十分麻煩了,何況有些方法是屬於標籤的生命週期方法,是由JSP引擎調用的,所以咱們只須要繼承Tag接口的實現子類便可,一般咱們使用「TagSupport」類或者「BodyTagSupport」類,能有更多的功能。ide

  在Tag接口中,除了getParent方法之外,其餘都是生命週期方法。在瀏覽器在解析一個JSP頁面時,遇到某個自定義標籤後就會開始執行該標籤的生命週期方法。自定義標籤的生命週期順序爲:① 建立自定義標籤的實例對象 ---> ② setPageContext方法 ---> ③ setParent方法---> ④ doStart方法 ---> ⑤ doEnd方法 ---> ⑥ release方法(一般在服務器關閉時才調用)。

  下面簡單的介紹下這幾個生命週期方法:

  setPageContext方法(重要),JSP引擎對標籤進行實例化對象後,會先調用setPageContext方法,將JSP頁面的pageContext對象傳入這個標籤處理器類,咱們在JSP的pageContext隱式對象一文中說過,只要擁有了pageContext對象,那麼就能夠獲取其餘八大隱式對象從而操做web中的需求了。

  setParent方法,在setPageContext方法執行完以後,將調用setParent方法,這個方法將會把這個自定義標籤的父類標籤(若是有)傳遞給該標籤處理器類,若是沒有父類標籤,那麼setParent方法的參數即爲null。注意,這裏說的標籤的父標籤也是指自定義標籤,若是該自定義標籤的只是嵌入在普通的HTML標籤的話那麼就是無父類標籤,執行的只是setParent(null)方法。

  doStartTag方法,當JSP引擎接連調用setPageContext方法和setParent方法完成標籤的配置以後,當瀏覽器解析標籤的開始標籤時,就會調用doStartTag方法。一般咱們在使用標籤處理某個功能時,就將該功能在doStartTag方法中覆寫。另外,依據doStartTag方法的返回值是「EVAL_BODY_INCLUDE」(執行)仍是「SKIP_BODY」(不執行)決定是否執行標籤體中的內容。能夠說這是咱們要使用標籤來封裝Java代碼最重要的一個方法。

  doEndTag方法,當瀏覽器在JSP頁面中解析到該標籤的結束標籤時,就會調用doEndTag方法。另外,依據doEndTag方法的返回值是「EVAL_PAGE」(執行)仍是「SKIP_PAGE」 (不執行)決定是否執行結束標籤以後餘下的JSP頁面內容。

  release方法,一般JSP調用完doEndTag方法後,並不會當即執行release方法,由於爲了服務器的性能,一般就會將標籤處理器類的對象駐留於內存中,以便下次能更快速地調用,這一點和Servlet是同樣的。通常在中止該web應用或服務器中止時纔會調用標籤處理器的release方法,釋放標籤中的資源。

 

  一般咱們使用的是一個Java類繼承TagSupport類或者BodyTagSupport類,對於處理標籤,依然也是覆寫doStartTag方法。同時注意到TagSupport類中,一個屬性即爲pageContext,注意這是字段,同時能給子類調用(protected修飾),而咱們基本在覆寫doStartTag方法中要隨處用到這個字段:

  

 

例1:使用自定義標籤來顯示來訪者IP

  建立一個Java類繼承TagSupport類,覆寫doStartTag方法,這裏由於標籤沒有標籤體,能夠暫時不用管doStartTag方法的返回值:

 1 package com.fjdingsd.tag;
 2 public class GuestIpTag extends TagSupport {
 3     @Override
 4     public int doStartTag() throws JspException {
 5         
 6         HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();
 7         String ip = request.getRemoteAddr();
 8         JspWriter out = this.pageContext.getOut();
 9         try {
10             out.write(ip);
11         } catch (IOException e) {
12             throw new RuntimeException(e);
13         }
14         return super.doStartTag();
15     }
16 }
View Code

接着在web應用的【WEB-INF】中建立TLD文件,設置好uri和標籤的名稱、類、以及標籤體類型:

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 
 3 <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
 6     version="2.0">
 7     <description>A tag library exercising SimpleTag handlers.</description>
 8     <tlib-version>1.0</tlib-version>
 9     <short-name>SimpleTagLibrary</short-name>
10     <uri>selftag</uri>
11     
12     <tag>
13         <name>guestip</name>
14         <tag-class>com.fjdingsd.tag.GuestIpTag</tag-class>
15         <body-content>empty</body-content>
16     </tag>
17 </taglib>
View Code

最後就能夠在JSP頁面中使用自定義標籤了,固然別忘了使用taglib指令先導入咱們的標籤所在的uri:

    <%@ taglib uri="selftag" prefix="selftag" %>

在JSP頁面的主體中使用咱們設計好的自定義標籤:

    您的ip地址爲:<selftag:guestip/>

瀏覽器中觀察:

  

 

例2:控制標籤的標籤體內容是否輸出顯示

         若是要想控制標籤體的內容是否輸出顯示,只須要修改doStartTag方法的返回值便可:

 1 package com.fjdingsd.tag;
 2 public class ShowTagBodyOrNot extends TagSupport {
 3     @Override
 4     public int doStartTag() throws JspException {
 5         HttpSession session = this.pageContext.getSession();
 6         User user = (User) session.getAttribute("user");
 7         if(user==null) {
 8             return TagSupport.SKIP_BODY;  //隱藏標籤體內容
 9         }else{
10             return TagSupport.EVAL_BODY_INCLUDE;  //顯示標籤體內容
11         }
12     }
13 }
View Code

在TLD文件中定義(這裏忽略文件首尾其餘定義):

1 <tag>
2         <name>showbody</name>
3         <tag-class>com.fjdingsd.tag.ShowTagBodyOrNot</tag-class>
4         <body-content>JSP</body-content>
5 </tag>
View Code

在JSP頁面中導入taglib指令後並在JSP頁面主體部分使用自定義標籤:

1     <selftag:showbody>
2             只有登陸用戶才能顯示……
3     </selftag:showbody>
View Code

  固然這個例子當我沒有在session域中存入User對象時,是不會在頁面上顯示這個標籤的標籤體內容的,這裏只是用來強調在doStartTag方法的返回值「EVAL_BODY_INCLUDE」與「SKIP_BODY」的區別。

 

例3:控制標籤以後餘下的JSP頁面是否輸出顯示

  若是要想標籤以後餘下的JSP頁面是否輸出顯示,只須要修改doEndTag方法的返回值便可:

 1 package com.fjdingsd.tag;
 2 public class ShowJSPOrNot extends TagSupport {
 3     //注意,TagSupport的doStartTag方法默認返回值爲SKIP_BODY,也就是不執行標籤體內容
 4     @Override
 5     public int doEndTag() throws JspException {
 6         HttpSession session = this.pageContext.getSession();
 7         User user = (User) session.getAttribute("user");
 8         if(user==null) {
 9             return TagSupport.SKIP_PAGE;  隱藏結束標籤後餘下JSP頁面        }else{
10             return TagSupport.EVAL_PAGE;  //顯示結束標籤後餘下JSP頁面
11         }
12     }
13 }
View Code

在TLD文件中定義(這裏忽略文件首尾其餘定義):

1 <tag>
2         <name>showpage</name>
3         <tag-class>com.fjdingsd.tag.ShowJSPOrNot</tag-class>
4         <body-content>empty</body-content>
5 </tag>
View Code

在JSP頁面中導入taglib指令後並在JSP頁面主體部分使用自定義標籤:

 1 <selftag:showpage/>
 2 
 3 <!DOCTYPE HTML>
 4 <html>
 5       <head>   
 6             <title>My JSP 'demo1.jsp' starting page</title>
 7       </head>
 8   
 9       <body>
10             。。。
11     <body>
12 </html>        
View Code

  這裏我把自定義標籤置於JSP頁面最開始的地方,能夠看到若是沒有在session域中存入User對象的話,那麼這個JSP在被訪問後是不會看到任何東西的,查看網頁源碼也是沒有任何代碼。固然這個例子只是用來強調在doEndTag方法的返回值 「EVAL_PAGE」和 「SKIP_PAGE」的區別。

  使用傳統的自定義標籤還能夠擴展一些其餘的功能,好比控制標籤體的內容重複執行,修改標籤體內容再輸出等等,這兩個功能涉及到使用Tag不一樣實現類的使用,將在下一篇博客中進行講解。

相關文章
相關標籤/搜索