自定义标签 (转载)
轉(zhuǎn)自:http://www.cnblogs.com/zhaoyang/archive/2011/12/25/2301108.html?
?
JSP自定義標(biāo)簽開發(fā)入門
JSP自定義標(biāo)簽開發(fā)入門
一般情況下開發(fā)jsp自定義標(biāo)簽需要引用以下兩個(gè)包
?
import?javax.servlet.jsp.*;
import?javax.servlet.jsp.tagext.*;
?
首先我們需要大致了解開發(fā)自定義標(biāo)簽所涉及到的接口與類的層次結(jié)構(gòu)(其中SimpleTag接口與SimpleTagSupport類是JSP2.0中新引入的)。
?
目標(biāo)1:自定義一個(gè)用表格顯示用戶信息的簡單標(biāo)簽
?
效果圖:
在jsp頁面使用此自定義標(biāo)簽:
?
假設(shè)我們有一個(gè)UserInfo的javabean,那么在JSP頁面使用此標(biāo)簽只需調(diào)用此標(biāo)簽即可
?
<!-- 創(chuàng)建需要展現(xiàn)UserInfo的實(shí)例(用于測試數(shù)據(jù)) -->
??? <%
??? UserInfo user =?new?UserInfo();
??? user.setUserName("Xuwei");
??? user.setAge(33);
??? user.setEmail("test@test.test");
??? pageContext.setAttribute("userinfo", user);??
??? %>
?
??? <!-- 給標(biāo)簽設(shè)置user屬性綁定要展現(xiàn)的UserInfo對象? -->
??? <cc:showUserInfo user="${pageScope.userinfo }"?/>
?
開發(fā)步驟:
?
簡單標(biāo)簽的開發(fā)我們只要實(shí)現(xiàn)Tag接口即可,為了簡單起見可以直接繼承實(shí)現(xiàn)了此接口的TagSupport類
?
1 創(chuàng)建自定義標(biāo)簽類
?
public?class?UserInfoTag?extends?TagSupport {
???
????private?UserInfo user;
?
??? @Override
????public?int?doStartTag()?throws?JspException {
????????try?{
??????????? JspWriter out =?this.pageContext.getOut();
????????????if(user ==?null) {
??????????????? out.println("No UserInfo Found...");
????????????????return?SKIP_BODY;
??????????? }
??????????? out.println("<table width='500px' border='1' align='center'>");
??????????? out.println("<tr>");
??????????? out.println("<td width='20%'>Username:</td>");
??????????? out.println("<td>" + user.getUserName() + "</td>");
??????????? out.println("</tr>");
??????????? out.println("<tr>");
??????????? out.println("<td>Age:</td>");
??????????? out.println("<td>" + user.getAge() + "</td>");
??????????? out.println("</tr>");
??????????? out.println("<tr>");
??????????? out.println("<td>Email:</td>");
??????????? out.println("<td>" + user.getEmail() + "</td>");
??????????? out.println("</tr>");
??????????? out.println("</table>");
??????? }?catch(Exception e) {
????????????throw?new?JspException(e.getMessage());
??????? }
????????return?SKIP_BODY;
??? }
???
??? @Override
????public?int?doEndTag()?throws?JspException {
????????return?EVAL_PAGE;
??? }
?
??? @Override
????public?void?release() {
????????super.release();
????????this.user =?null;
??? }
???
??? //getter and setters
????public?UserInfo getUser() {
????????return?user;
??? }
????public?void?setUser(UserInfo user) {
????????this.user = user;
??? }
}
?
2 在Web-Inf創(chuàng)建標(biāo)簽庫描述文件.tdl(Tag Library Description)
?
<?xml version="1.0"?encoding="UTF-8"?>
<taglib version="2.0"?xmlns="http://java.sun.com/xml/ns/j2ee"
?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
?xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>cc</short-name>
<uri>/mytaglib</uri>
<tag>
??? <name>showUserInfo</name>
??? <tag-class>com.mytags.UserInfoTag</tag-class>
??? <body-content>empty</body-content>
??? <attribute>
??????? <name>user</name>
?? ????? <required>false</required>
?? ????? <rtexprvalue>true</rtexprvalue>
??? </attribute>
?</tag>
</taglib>
?
3 配置web.xml
?
<jsp-config>
? ? <taglib>
? ????? <taglib-uri>/mytaglib</taglib-uri>
? ????? <taglib-location>/WEB-INF/mytaglib.tld</taglib-location>
? ? </taglib>
? </jsp-config>
?
4 在需要使用此標(biāo)簽的jsp頁面頭部引入
?
<%@ taglib uri="/mytaglib" prefix="cc"%>
?
5 使用(參照上面的使用步驟)
?
此致,一個(gè)簡單的JSP標(biāo)簽開發(fā)完成
?
標(biāo)簽類說明:
我們創(chuàng)建的UserInfoTag類繼承了TagSupport類,而它又實(shí)現(xiàn)了Tag接口,Tag接口的生命周期由其所在的容器控制,如下圖:
?
setPageContext() 將所在jsp頁面的pageContext注入進(jìn)來,目的是為了在后面的方法中可以訪問到j(luò)sp頁面對象的pageContext屬性
?
setParent()?????? 設(shè)置此標(biāo)簽的父標(biāo)簽
?
setAttribute()?? 將標(biāo)簽中的屬性注入到此class的屬性,不需要自己實(shí)現(xiàn)但要提供屬性的get與set方法
?
doStartTag()????? 在開始標(biāo)簽屬性設(shè)置后調(diào)用,如果返回SKIP_BODY則忽略標(biāo)簽之中的內(nèi)容,如果返回EVAL_BODY_INCLUDE則將標(biāo)簽體的內(nèi)容進(jìn)行輸出
?
doEndTag()???????? 在結(jié)束標(biāo)簽之前調(diào)用,返回SKIP_PAGE跳過整個(gè)jsp頁面后面的輸出,返回EVAL_PAGE執(zhí)行頁面余下部分
?
release()????????? 生命周期結(jié)束時(shí)調(diào)用
?
特別說明:在tomcat4.1之后的版本中默認(rèn)開啟了標(biāo)簽緩沖池(websphere和weblogic并不會這么做),所以執(zhí)行完標(biāo)簽后并不會執(zhí)行release()方法(_jspDestroy()時(shí)才釋放),也就是說同一個(gè)jsp頁面自定義標(biāo)簽不管使用多少次只會存在一個(gè)實(shí)例,但也并不是每一個(gè)標(biāo)簽都會為其創(chuàng)建一個(gè)緩沖池,要根據(jù)參數(shù)來判斷,例如:
<cc:UserInfoTag user=”…” />
<cc:UserInfoTag />
上面例子中由于參數(shù)不同就會創(chuàng)建兩個(gè)標(biāo)簽緩沖池。
?
這個(gè)問題可以通過設(shè)定tomcat的配置文件加以解決:
在%tomcat%\conf\web.xml加入enablePooling參數(shù),并設(shè)置為false(不緩存自定義標(biāo)簽)。
<init-param>
? <param-name>enablePooling</param-name>
? <param-value>false</param-value>
</init-param>
?
清空%tomcat%\conf\目錄
-------------------------------------------------------------------------------------------------------------------------------
TagSupport類已經(jīng)為我們實(shí)現(xiàn)并擴(kuò)展了一些方法(比如在上述方法中我們可以直接使用pageContext對象,調(diào)用父標(biāo)簽getParent()等),所以一般情況下我們只需重寫doStartTag(),doEndTag() 即可
?
TLD文件說明:
<!--版本號-->
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>cc</short-name>
<tag>
<!—指定標(biāo)簽名 -->
??? <name>showUserInfo</name>
<!—指定標(biāo)簽類文件的全路徑 -->
??? <tag-class>com.mytags.UserInfoTag</tag-class>
<!--如果不需要標(biāo)簽體則設(shè)置empty,反之設(shè)定jsp -->
??? <body-content>empty</body-content>
<!—設(shè)定屬性(如果有的話) -->
??? <attribute>
<!—指定標(biāo)簽名 -->
?????? <name>user</name>
<!—是否是必須,如果非必須沒設(shè)置則為空 -->
?? ???? <required>false</required>
<rtexprvalue>true</rtexprvalue><!—是否可在屬性中使用表達(dá)式 -->
??? </attribute>
</tag>
?
?
Web.xml文件說明:
<jsp-config>
? ? <taglib>
<!--
標(biāo)簽庫的uri路徑
即jsp頭文件中聲明<%@ taglib uri="/mytaglib" prefix="cc"%>
的uri
?-->
? ????? <taglib-uri>/mytaglib</taglib-uri>
<!—tld文件所在的位置-->
? ????? <taglib-location>/WEB-INF/mytaglib.tld</taglib-location>
? ? </taglib>
? </jsp-config>
?
?
目標(biāo)2:自定義一個(gè)類似于Asp.Net中的Reapter控件的標(biāo)簽
效果圖:
?
在jsp頁面使用此自定義標(biāo)簽:
?
<!-- 創(chuàng)建需要展現(xiàn)javabean(UserInfo)集合的實(shí)例(用于測試數(shù)據(jù)) -->
<%
??? List<UserInfo> users =?new?ArrayList<UserInfo>();???
??? users.add(new?UserInfo("Zhangsan", 12, "Zhangsan@163.com"));
??? users.add(new?UserInfo("Lisi", 22, "Lisi@sina.com"));
??? users.add(new?UserInfo("Wangwu", 33, "Wangwu@qq.com"));
??? pageContext.setAttribute("users", users);
%>
?
<!-- 給標(biāo)簽綁定數(shù)據(jù)源? -->
<table width='500px'?border='1'?align='center'>
??? <tr>
??? ??? <td width='20%'>UserName</td>
??? ??? <td width='20%'>Age</td>
??? ??? <td>Email</td>
??? </tr>
??? <cc:repeater var="item"?items="${pageScope.users }">
??? ??? <tr>
??? ??? ??? <td>${item.userName }</td>
??? ??? ??? <td>${item.age }</td>
??? ??? ??? <td>${item.email }</td>
??? ??? </tr>
??? </cc:repeater>
</table>
?
開發(fā)步驟:
?
要完成此控件我們需要實(shí)現(xiàn)一個(gè)迭代接口,即IterationTag,由于TagSupport同樣實(shí)現(xiàn)了此接口,所以我們繼承此類
?
1 創(chuàng)建自定義標(biāo)簽類
?
public?class?Repeater?extends?TagSupport {
????private?Collection?items;
????private?Iterator?it;
????private?String var;
?
??? @Override
????public?int?doStartTag()?throws?JspException {
????????if(items ==?null?|| items.size() == 0)?return?SKIP_BODY;
??????? it = items.iterator();??
??????? if(it.hasNext()) {
??????????? pageContext.setAttribute(var, it.next());
??????? }
????????return?EVAL_BODY_INCLUDE;
??? }
???
??? @Override
????public?int?doAfterBody()?throws?JspException {
????????if(it.hasNext()) {
??????????? pageContext.setAttribute(var, it.next());
????????????return?EVAL_BODY_AGAIN;
??????? }
????????return?SKIP_BODY;
??? }
???
??? @Override
????public?int?doEndTag()?throws?JspException {
????????return?EVAL_PAGE;
??? }
???
????public?void?setItems(Collection?items) {
????????this.items = items;
??? }
???
????public?void?setVar(String var) {
????????this.var = var;
??? }
}
?
2在Web-Inf創(chuàng)建標(biāo)簽庫描述文件.tdl(Tag Library Description)
由于目標(biāo)1種已經(jīng)創(chuàng)建了此文件,我們只需增加此標(biāo)簽的配置即可
?
<tag>
??? <name>repeater</name>
??? <tag-class>com.mytags.Repeater</tag-class>
??? <body-content>jsp</body-content>
??? <attribute>
??????? <name>items</name>
??????? <required>false</required>
??????? <rtexprvalue>true</rtexprvalue>
??? </attribute>
??? <attribute>
??????? <name>var</name>
??????? <required>true</required>
??????? <rtexprvalue>true</rtexprvalue>
??? </attribute>
?</tag>
?
3 配置web.xml (目標(biāo)1中已完成,無需修改)
?
4 在需要使用此標(biāo)簽的jsp頁面頭部引入
<%@ taglib uri="/mytaglib" prefix="cc"%>
?
5 使用(參照上面的使用步驟)
?
標(biāo)簽類說明:
我們用到了迭代接口,以下是容器處理此接口的流程
?
?
作為目標(biāo)1中的補(bǔ)充: 在doAfterBody()如果返回值是EVAL_BODY_AGAIN那么將重新執(zhí)行此方法
?
目標(biāo)3:使用BodyTagSupport
此目標(biāo)并不會使用實(shí)際例子進(jìn)行顯示,主要是說明為什么,什么情況下需要使用到BodyTag接口或者BodyTagSupport類?
如果我們需要在<test>? ….?? </test>之間的標(biāo)簽體的頭部和尾部加上一些標(biāo)記或者是其他處理,一般的處理方法是在doStartTag和doEndTag方法中進(jìn)行, 但是如果是個(gè)迭代標(biāo)簽,標(biāo)簽體的每段內(nèi)容在循環(huán)輸出時(shí)每次都需要在頭部和尾部加上一些標(biāo)記,我們使用BodyTagSupport就很方便了,
?
此接口在doStartTag()方法返回值多了一個(gè)EVAL_BODY_BUFFERED,它將對主體進(jìn)行計(jì)算,并輸出到緩沖區(qū)(注:此處是緩沖區(qū)并非直接輸出到客戶端,需要我們手動(this.bodyContent.getEnclosingWriter().write(this.bodyContent.getString());)進(jìn)行輸出客戶端的調(diào)用,否則主體內(nèi)容不會進(jìn)行顯示)
?
標(biāo)簽類說明:
關(guān)于BodyTagSupport接口的說明
?
目標(biāo)4:自定義的函數(shù)庫
1 創(chuàng)建函數(shù)庫類
?
public?class?MyFunctions {
????public?static?String formatMyName(String name) {
???????return?"your name is " + name;
??? }
????public?static?int?add(int?a,?int?b) {
???????return?a+b;
??? }
}
?
2 在TLD文件中配置 (引用于目標(biāo)1中的tld文件)
<function>
??? <name>formatMyName</name>
??? <function-class>com.taglib.MyFunctions</function-class>
??? <function-signature>java.lang.String formatMyName(java.lang.String)</function-signature>
?</function>
?
<function>
??? <name>add</name>
??? <function-class>com.taglib.MyFunctions</function-class>
??? <function-signature>java.lang.String add(int,?int)</function-signature>
?</function>
?
3 JSP中調(diào)用
?
${cc:formatMyName("wangfei") }
${cc:add(12, 34) }
轉(zhuǎn)載于:https://www.cnblogs.com/heling/archive/2012/08/03/2622187.html
總結(jié)
以上是生活随笔為你收集整理的自定义标签 (转载)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: A+B/A*B求A和B
- 下一篇: 30个创意出色的非常实用的jquery框