熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

JSP自定義標簽開發入門

2013-11-15 11:53:04  來源: JSP教程 

  一般情況下開發jsp自定義標簽需要引用以下兩個包

  import javaxservletjsp*;

  import javaxservletjsptagext*;

  首先我們需要大致了解開發自定義標簽所涉及到的接口與類的層次結構(其中SimpleTag接口與SimpleTagSupport類是JSP中新引入的)

  目標:自定義一個用表格顯示用戶信息的簡單標簽

  效果圖

  在jsp頁面使用此自定義標簽

  假設我們有一個UserInfo的javabean那麼在JSP頁面使用此標簽只需調用此標簽即可

  

  1. <! 創建需要展現UserInfo的實例(用於測試數據) 
  2.     <%  
  3.     UserInfo user = new UserInfo();  
  4.     usersetUserName("Xuwei");  
  5.     usersetAge();  
  6.     usersetEmail("test@testtest");  
  7.     pageContextsetAttribute("userinfo" user);    
  8.     %> 
  9.    
  10.     <! 給標簽設置user屬性綁定要展現的UserInfo對象  
  11.     <cc:showUserInfo user="${pageScopeuserinfo }" /> 

  開發步驟

  簡單標簽的開發我們只要實現Tag接口即可為了簡單起見可以直接繼承實現了此接口的TagSupport類

   創建自定義標簽類

  

  1. public class UserInfoTag extends TagSupport {  
  2.      
  3.     private UserInfo user;  
  4.    
  5.     @Override  
  6.     public int doStartTag() throws JspException {  
  7.         try {  
  8.             JspWriter out = thispageContextgetOut();  
  9.             if(user == null) {  
  10.                 outprintln("No UserInfo Found");  
  11.             &

  
nbsp;   return SKIP_BODY;  

  •             }  
  •             outprintln("<table width=px border= align=center>");  
  •             outprintln("<tr>");  
  •             outprintln("<td width=%>Username:</td>");  
  •             outprintln("<td>" + usergetUserName() + "</td>");  
  •             outprintln("</tr>");  
  •             outprintln("<tr>");  
  •             outprintln("<td>Age:</td>");  
  •             outprintln("<td>" + usergetAge() + "</td>");  
  •             outprintln("</tr>");  
  •             outprintln("<tr>");  
  •             outprintln("<td>Email:</td>");  
  •             outprintln("<td>" + usergetEmail() + "</td>");  
  •             outprintln("</tr>");  
  •             outprintln("</table>");  
  •         } catch(Exception e) {  
  •             throw new JspException(egetMessage());  
  •         }  
  •         return SKIP_BODY;  
  •     }  
  •      
  •     @Override  
  •     public int doEndTag() throws JspException {  
  •    &nbs

  
p;    return EVAL_PAGE;  

  •     }  
  •    
  •     @Override  
  •     public void release() {  
  •         superrelease();  
  •         thisuser = null;  
  •     }  
  •      
  •     //getter and setters  
  •     public UserInfo getUser() {  
  •         return user;  
  •     }  
  •     public void setUser(UserInfo user) {  
  •         thisuser = user;  
  •     }  
  • }  
  •   

   在WebInf創建標簽庫描述文件tdl(Tag Library Description)

  

  1. <?xml version="" encoding="UTF"?> 
  2. <taglib version="" xmlns="
  3.  xmlns:xsi="
  4.  xsi:schemaLocation="
  5. <tlibversion></tlibversion> 
  6. <jspversion></jspversion> 
  7. <shortname>cc</shortname> 
  8. <uri>/mytaglib</uri> 
  9. <tag> 
  10.     <name>showUserInfo</name> 
  11.     <tagclass>commytagsUserInfoTag</tagclass> 
  12.     <bodycontent>empty</bodycontent> 
  13.     <attribute> 
  14.         <name>user</name> 
  15.          <required>false</required> 
  16.          <rtexprvalue>true</rtexprvalue> 
  17.     </attribute> 
  18.  </tag> 
  19. </taglib> 

   配置webxml

  

  1. <jspconfig> 
  2.     <taglib> 
  3.         <tagliburi>/mytaglib</tagliburi>&n

  
bsp;

  •         <tagliblocation>/WEBINF/mytaglibtld</tagliblocation> 
  •     </taglib> 
  •   </jspconfig> 

   在需要使用此標簽的jsp頁面頭部引入

  

  1. <%@ taglib uri="/mytaglib" prefix="cc"%> 

   使用(參照上面的使用步驟)

  此致一個簡單的JSP標簽開發完成

  標簽類說明

  我們創建的UserInfoTag類繼承了TagSupport類而它又實現了Tag接口Tag接口的生命周期由其所在的容器控制如下圖

  setPageContext() 將所在jsp頁面的pageContext注入進來目的是為了在後面的方法中可以訪問到jsp頁面對象的pageContext屬性

  setParent() 設置此標簽的父標簽

  setAttribute() 將標簽中的屬性注入到此class的屬性不需要自己實現但要提供屬性的get與set方法

  doStartTag() 在開始標簽屬性設置後調用如果返回SKIP_BODY則忽略標簽之中的內容如果返回EVAL_BODY_INCLUDE則將標簽體的內容進行輸出

  doEndTag() 在結束標簽之前調用返回SKIP_PAGE跳過整個jsp頁面後面的輸出返回EVAL_PAGE執行頁面余下部分

  release() 生命周期結束時調用

  特別說明在tomcat之後的版本中默認開啟了標簽緩沖池(websphere和weblogic並不會這麼做)所以執行完標簽後並不會執行release()方法(_jspDestroy()時才釋放)也就是說同一個jsp頁面自定義標簽不管使用多少次只會存在一個實例但也並不是每一個標簽都會為其創建一個緩沖池要根據參數來判斷例如

  

  1. <cc:UserInfoTag user=”…” /> 
  2. <cc:UserInfoTag /> 

  上面例子中由於參數不同就會創建兩個標簽緩沖池

  這個問題可以通過設定tomcat的配置文件加以解決

  在%tomcat%\conf\webxml加入enablePooling參數並設置為false(不緩存自定義標簽)

  

  1. <initparam> 
  2.   <paramname>enablePooling</paramname> 
  3.   <paramvalue>false</paramvalue> 
  4. </initparam> 

  清空%tomcat%\conf\目錄

  TagSupport類已經為我們實現並擴展了一些方法(比如在上述方法中我們可以直接使用pageContext對象調用父標簽getParent()等)所以一般情況下我們只需重寫doStartTag()doEndTag() 即可

  TLD文件說明

  <!版本號>
<tlibversion></tlibversion>
<jspversion></jspversion>
<shortname>cc</shortname>
<tag>
<!—指定標簽名 >
<name>showUserInfo</name>
<!—指定標簽類文件的全路徑 >
<tagclass>commytagsUserInfoTag</tagclass>
<!如果不需要標簽體則設置empty反之設定jsp >
<bodycontent>empty</bodycontent>
<!—設定屬性(如果有的話) >
<attribute>
<!—指定標簽名 >
<name>user</name>
<!—是否是必須如果非必須沒設置則為空 >
<required>false</required>
<rtexprvalue>true</rtexprvalue><!—是否可在屬性中使用表達式 >
</attribute>
</tag>

  Webxml文件說明

  <jspconfig>
<taglib>
<!

  標簽庫的uri路徑
即jsp頭文件中聲明<%@ taglib uri="/mytaglib" prefix="cc"%>
的uri
>
<tagliburi>/mytaglib</tagliburi>
<!—tld文件所在的位置>
<tagliblocation>/WEBINF/mytaglibtld</tagliblocation>
</taglib>
</jspconfig>

  目標:自定義一個類似於AspNet中的Reapter控件的標簽

  效果圖

  在jsp頁面使用此自定義標簽

  

  1. <! 創建需要展現javabean(UserInfo)集合的實例(用於測試數據) 
  2. <%  
  3.     List<UserInfo> users = new ArrayList<UserInfo>();     
  4.     usersadd(new UserInfo("Zhangsan"  "Zhangsan@com"));  
  5.     usersadd(new UserInfo("Lisi"  "Lisi@sinacom"));  
  6.     usersadd(new UserInfo("Wangwu"  "Wangwu@qqcom"));  
  7.     pageContextsetAttribute("users" users);  
  8. %> 
  9.    
  10. <! 給標簽綁定數據源  
  11. <table width=px border= align=center
  12.     <tr> 
  13.         <td width=%>UserName</td> 
  14.         <td width=%>Age</td> 
  15.         <td>Email</td> 
  16.     </tr> 
  17.     <cc:repeater var="item" items="${pageScopeusers }"> 
  18.         <tr> 
  19.             <td>${itemuserName }</td> 
  20.             <td>${itemage }</td> 
  21.             <td>${itememail }</td> 
  22.         </tr> 
  23.     </cc:repeater> 
  24. </table> 

  
;

  開發步驟

  要完成此控件我們需要實現一個迭代接口即IterationTag由於TagSupport同樣實現了此接口所以我們繼承此類

   創建自定義標簽類

  

  1. public class Repeater extends TagSupport {  
  2.     private Collection items;  
  3.     private Iterator it;  
  4.     private String var;  
  5.    
  6.     @Override  
  7.     public int doStartTag() throws JspException {  
  8.         if(items == null || itemssize() == ) return SKIP_BODY;  
  9.         it = itemsiterator();    
  10.         if(ithasNext()) {  
  11.             pageContextsetAttribute(var itnext());  
  12.         }  
  13.         return EVAL_BODY_INCLUDE;  
  14.     }  
  15.      
  16.     @Override  
  17.     public int doAfterBody() throws JspException {  
  18.         if(ithasNext()) {  
  19.             pageContextsetAttribute(var itnext());  
  20.             return EVAL_BODY_AGAIN;  
  21.         }  
  22.         return SKIP_BODY;  
  23.     }  
  24.      
  25.     @Override  
  26.     public int doEndTag() throws JspException {  
  27.         return EVAL_PAGE;  
  28.     }  
  29.      
  30.     public void setItems(Collection items) {  
  31.         thisitems = items;  
  32.     }  
  33.      
  34.     public void setVar(String var) {  
  35.      &

  
nbsp;  thisvar = var;  

  •     }  

  在WebInf創建標簽庫描述文件tdl(Tag Library Description)由於目標種已經創建了此文件我們只需增加此標簽的配置即可

  

  1. <tag> 
  2.     <name>repeater</name> 
  3.     <tagclass>commytagsRepeater</tagclass> 
  4.     <bodycontent>jsp</bodycontent> 
  5.     <attribute> 
  6.         <name>items</name> 
  7.         <required>false</required> 
  8.         <rtexprvalue>true</rtexprvalue> 
  9.     </attribute> 
  10.     <attribute> 
  11.         <name>var</name> 
  12.         <required>true</required> 
  13.         <rtexprvalue>true</rtexprvalue> 
  14.     </attribute> 
  15.  </tag> 
  16.   

   配置webxml (目標中已完成無需修改)

  

在需要使用此標簽的jsp頁面頭部引入

  

  1. <%@ taglib uri="/mytaglib" prefix="cc"%> 

   使用(參照上面的使用步驟)

  標簽類說明

  我們用到了迭代接口以下是容器處理此接口的流程

  作為目標中的補充 在doAfterBody()如果返回值是EVAL_BODY_AGAIN那麼將重新執行此方法

  目標:使用BodyTagSupport

  此目標並不會使用實際例子進行顯示主要是說明為什麼什麼情況下需要使用到BodyTag接口或者BodyTagSupport類?

  如果我們需要在 … 之間的標簽體的頭部和尾部加上一些標記或者是其他處理一般的處理方法是在doStartTag和doEndTag方法中進行 但是如果是個迭代標簽標簽體的每段內容在循環輸出時每次都需要在頭部和尾部加上一些標記我們使用BodyTagSupport就很方便了

  此接口在doStartTag()方法返回值多了一個EVAL_BODY_BUFFERED它將對主體進行計算並輸出到緩沖區(注此處是緩沖區並非直接輸出到客戶端需要我們手動(thisbodyContentgetEnclosingWriter()write(thisbodyContentgetString());)進行輸出客戶端的調用否則主體內容不會進行顯示)

  標簽類說明

  關於BodyTagSupport接口的說明

  目標:自定義的函數庫
>

   創建函數庫類

  

  1. public class MyFunctions {  
  2.     public static String formatMyName(String name) {  
  3.        return "your name is " + name;  
  4.     }  
  5.     public static int add(int a int b) {  
  6.        return a+b;  
  7.     }  

   在TLD文件中配置 (引用於目標中的tld文件)

  

  1. <function> 
  2.     <name>formatMyName</name> 
  3.     <functionclass>comtaglibMyFunctions</functionclass> 
  4.     <functionsignature>javalangString formatMyName(javalangString)</functionsignature> 
  5.  </function> 
  6.    
  7. <function> 
  8.     <name>add</name> 
  9.     <functionclass>comtaglibMyFunctions</functionclass> 
  10.     <functionsignature>javalangString add(int int)</functionsignature> 
  11.  </function> 

   JSP中調用

  

  1. ${cc:formatMyName("wangfei") }  
  2. ${cc:add( ) } 


From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19809.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.