堅持每天寫博文,積累下開發中的點點滴滴
繼承TagSupport:
首先創建一個普通java類MyTagText繼承TagSupport,該類爲某一標籤定義操作。
重寫父類的setPageContext方法,用於得到當前jsp頁面的pageContext對象。
重寫父類的doStartTag方法,定義標籤具體操作
public class MyTagText extends TagSupport{
private PageContext pageContext;
//重寫父類的setPageContext方法,用於得到當前jsp頁面的pageContext對象。
@Override
public void setPageContext(PageContext pageContext) {
this.pageContext = pageContext;
}
//重寫父類的doStartTag方法,裏面寫上你定義的標籤的java操作
//這裏我定義的標籤用作向瀏覽器輸出一大段信息:
@Override
public int doStartTag() throws JspException {
try {
pageContext.getResponse().getWriter().write("AAAAAAAAA");
} catch (Exception e) {
e.printStackTrace();
}
return super.doStartTag();
}
//這樣就完成一個標籤處理程序了.寫完程序我們還需要註冊它。
}
我們需要在tld文件中註冊
在你的web應用目錄下,找到WEB-INF文件夾,在裏面新建一個tld類型的文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version><!-- 代表標籤庫的版本號 -->
<jsp-version>1.2</jsp-version><!-- 代表jsp的版本 -->
<short-name>mtt</short-name><!-- 你的標籤庫的簡稱 -->
<uri>http://vmaxtam.com/mytag</uri><!-- 你標籤庫的引用uri -->
<tag>
<name>mytab</name><!-- 你定義的標籤的名稱 -->
<tag-class>CustomTag.MyTagText</tag-class><!-- 對應的標籤處理程序:包名+類名 -->
<body-content>JSP</body-content><!-- 標籤體內容的格式 -->
</tag>
</taglib>
現在可以在JSP中使用了記得導入標籤:<%@taglib uri="http://vmaxtam.com/mytag" prefix="mmt" %>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@taglib uri="http://vmaxtam.com/mytag" prefix="mmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<mmt:mytab></mmt:mytab>
</body>
</html>
效果如下:
參考:https://www.cnblogs.com/vmax-tam/p/4145334.html 作者:白Rime
自定義標籤的原理
1)當服務器打開時,就會加載WEB-INF下的資源文件,包括web.xml 和 tld文件,把它們加載到內存
2)我們在瀏覽器輸入http://localhost:8080/TestArea/testit.jsp來訪問jsp頁面
3)服務器讀取testit.jsp裏的內容,當讀到
<%@taglib uri="http://vmaxtam.com/mytag" prefix="mmt" %>
這一句的時候,就會在內存中找是否存在uri爲http://vmaxtam.com/mytag的tld文件,找不到就會報錯
4)繼續讀取jsp頁面,讀到<mmt:mytag>這個標籤的時候,就會通過uri去找到tld文件,在tld文件中找到mytab是否被定義,是的話就得到它的tag-class的內容,然後去找到它對應的標籤處理程序
5)實例化標籤處理程序,利用生成的對象調用它裏面的方法
這裏服務器對標籤處理程序裏的方法也有一定的調用順序 A)void setPageContext(PageContext pc) --傳入pageContext對象
B)void setParent(Tag t) --如果有父標籤,傳入父標籤對象,如果沒有,則傳入null
C)int doStartTag() --開始執行標籤時調用。
D)int doEndTag() --結束標籤時調用
E)void release() --釋放資源
如果你沒有重寫上面的方法,系統將會調用它的父類裏的方法~
爲什麼會是這個順序調用,是有證據的,下面我們來看看jsp被翻譯爲java源文件裏的截取:
private boolean _jspx_meth_itcast_005fshowIp_005f0(PageContext _jspx_page_context) throws Throwable { PageContext pageContext = _jspx_page_context; JspWriter out = _jspx_page_context.getOut(); // itcast:showIp 1) 實例化ShowIpTag對象 gz.itcast.tag.ShowIpTag _jspx_th_itcast_005fshowIp_005f0 = (gz.itcast.tag.ShowIpTag) _005fjspx_005ftagPool_005fitcast_005fshowIp_005fnobody.get(gz.itcast.tag.ShowIpTag.class); 2)調用setPageContext方法 _jspx_th_itcast_005fshowIp_005f0.setPageContext(_jspx_page_context); 3)調用setParent方法 _jspx_th_itcast_005fshowIp_005f0.setParent(null); 4)調用doStartTag方法 int _jspx_eval_itcast_005fshowIp_005f0 = _jspx_th_itcast_005fshowIp_005f0.doStartTag(); 5)調用doEndTag方法 if (_jspx_th_itcast_005fshowIp_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) { _005fjspx_005ftagPool_005fitcast_005fshowIp_005fnobody.reuse(_jspx_th_itcast_005fshowIp_005f0); return true; } _005fjspx_005ftagPool_005fitcast_005fshowIp_005fnobody.reuse(_jspx_th_itcast_005fshowIp_005f0); return false; }
自定義標籤可以可控制標籤體內的文本 和 結束標籤後的文本是否輸出~
@Override//遇到開始標籤時執行的方法 public int doStartTag() throws JspException { //return Tag.SKIP_BODY; //標籤體內容不向瀏覽器輸出 return Tag.EVAL_BODY_INCLUDE;//標籤體內容向瀏覽器輸出 } @Override//遇到結束標籤後執行的方法 public int doEndTag() throws JspException { //return Tag.EVAL_PAGE;//結束標籤後的內容輸出到瀏覽器 return Tag.SKIP_PAGE;//結束標籤後的內容不輸出到瀏覽器 }
那麼如何重複輸出標籤體內的文本內容呢?TagSupper還提供了一個doAftetBody方法,我們只需要這樣做:
int i = 4; @Override//每輸出一次標籤體的內容都會調用一次這個方法 public int doAfterBody() throws JspException { while(true) { if(i>0) { i--; return IterationTag.EVAL_BODY_AGAIN;//再執行一次便籤體內的內容 }else{ break; } } return Tag.SKIP_BODY;//不輸出標籤體的內容 }