這個前面也就是匆匆帶過了,還是好好描述一番吧。
什么是自定義標簽兒。就是在jsp頁面中,我們自己生成定義的標簽兒,可以處理一定的邏輯。所以本質上還是要有java代碼來處理的。
自定義標簽兒能夠運行的三個要素:
1、對應的java處理程序。
2、tld標簽兒語言定義
3、在.jsp文件中導入包兒,並且,在頁面中使用。
那么在3中得到導入路徑,通過3知道對應的tld文件,那么一定是在tld中有對應的java包的引入。這樣三者構成一種連接關系,那么代碼就能執行了。
下面以分頁為例,來簡單闡述這個自定義標簽兒。
從頁面開始:

效果:
標簽兒部分:
<p align="center"> <page:page pageSize="${pageBean.pageSize }" historical="" method="" url="BookServlet.do" currentPage="${pageBean.currentPage }" count="${pageBean.count }"/> </p>
引入部分:
<%@ taglib uri="http://com.letben.tag" prefix = "page" %>
接下來要通過這個 uri找到tld文件。
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee " version="2.1"> <description>pageTag</description> <display-name>pageTag</display-name> <tlib-version>1.1</tlib-version> <short-name>letben</short-name> <uri>http://com.letben.tag</uri><!-- 在這里就發現了,這個路徑,那么就可以通過前面頁面里的uri找到這個tld文件。 --> <tag> <name>page</name> <tag-class>com.letben.tag.PageTag</tag-class><!-- 發現這個文件能夠對應到一個 PageTag的包。 --> <body-content>empty</body-content> <attribute> <name>currentPage</name><!-- 標簽兒中出現的屬性名 --> <required>true</required><!-- 是否必須出現,是,由於這里面當時忘記了,這個的存在,導致在后面的項目在使用ssh框架的時候,多寫了三個屬性以及對應的get 和set方法。private String historical,private String method,和什么吧,忘記了,主要是因為 這些屬性在只使用servlet開發的時候,這些東西還是有必要給上的,但是在ssh框架里面不再需要了,所以 多寫了這樣一些沒有用的屬性和方法。--> <rtexprvalue>true</rtexprvalue><!-- 是否允許值的改寫,是 --> </attribute> <attribute> <name>count</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>pageSize</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>url</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>historical</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>method</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
這樣到PageTag里面,去看看究竟。
package com.letben.tag; import java.io.IOException; import java.text.MessageFormat; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; public class PageTag extends TagSupport { private int count=0; private int currentPage=1; private int pageSize = 5; private String url; private String method; private String historical; public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getHistorical() { return historical; } public void setHistorical(String historical) { this.historical = historical; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } @Override public int doStartTag() throws JspException { int totalPage = count%pageSize==0?count/pageSize:count/pageSize+1; if(currentPage<=1){ currentPage = 1; } if(currentPage>=totalPage){ currentPage = totalPage; } //<a href="BookServlet.do?page=3&historical=yes&method=somehow" >超級鏈接</a> String linkPattern = "<a href=\"{0}?page={1}&historical={3}&method={4}\">{2}</a>"; String first = MessageFormat.format(linkPattern, url,1,"首頁",historical,method);//<a href=bookservlet.do?page=1&historical=yes&method=add>首頁</a> String pre = MessageFormat.format(linkPattern, url,currentPage-1,"上一頁",historical,method); String next = MessageFormat.format(linkPattern,url,currentPage+1,"下一頁",historical,method); String last = MessageFormat.format(linkPattern, url,totalPage,"尾頁",historical,method); if(currentPage<=1){ first = "首頁"; pre = "上一頁"; } if(currentPage>=totalPage){ next = "下一頁"; last = "尾頁"; } String htmlString = "{0} {1} {2} {3} 共 {4} 頁,{5} 條記錄。當前第 {6} 頁,分頁單位是 {7} 條記錄"; //<a href=bookservlet.do?page=1&historical=yes&method=add>首頁</a> <a href=bookservlet.do?page=1&historical=yes&method=add>下一頁</a> //<a href=bookservlet.do?page=1&historical=yes&method=add>首頁</a> htmlString = MessageFormat.format(htmlString, first,pre,next,last,totalPage,count,currentPage,pageSize); JspWriter out = this.pageContext.getOut(); try { out.println(htmlString); } catch (IOException e) { System.out.println("輸出標簽時,出現異常"); e.printStackTrace(); } return this.EVAL_PAGE; } }
發現doStartTag()還比較有用,就是 在頁面,在生成當前標簽兒之前,會執行這個·方法。回顧頁面,頁面要輸出的就是一些超級鏈接。本質上就是一堆html代碼。
那么要在這里把它拼接出來。然后通過 當前頁得到輸出流對象,把它打印到前台就好了。那么具體要打印什么,就需要里面接一下了。拼接方式 使用了一個字符串的拼接模板方式。
舉個例子就是:String pattern = "my name is {0} my age is {1}";
String outString = MessageFormat.format(pattern,"lifei",23);
輸出的結果就是: my name is lifei ma age is 23.
就這樣一個 結果。所以如法炮制得到這樣一個 分頁 的htmlString。
還有效果更棒的哦,這個只是1.0版本,下面有一個 1.6版本的分頁,十分穩定,主要是 字符串拼接有一些邏輯要格外注意。
期望樣式,下面給了,並且也給出了每個版本修復的bug。
package com.letben.tag; import java.io.IOException; import java.text.MessageFormat; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; /** * PageTag 1.1 解決了,歷史分頁問題。 * PageTag 1.2 嘗試配出老師需要的模板,是個 過渡版本。存在嚴重bug!!! * PageTag 1.3 版本,並不存在十分嚴重bug。算法是對的。應用場景,有點兒小bug。忘了考慮上下幾頁的問題。 * PageTag 1.4 版本,能夠顯示分頁了。應該是 各種bug都沒有了,並且 能很好地 顯示分頁。最后一頁顯示條目有bug。 * PageTag 1.5 版本,必須各種bug沒有了!!!。能夠完美顯示,並且最后一頁有幾條項目,就顯示多少個條目。 * PageTag 1.6 版本,消除了,未獲得數據時,回報的by zero。異常。 * PageTag 1.61 版本,多一個判非條件。之前僅一個 不合適,可能會存在異常。 * @author RealisedBy : Letben TaughtBy : Salmon At Dec.16th */ public class PageTag extends TagSupport { private int count=0; private int currentPage=1; private int pageSize = 5; private String url; private String method; private String historical; public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getHistorical() { return historical; } public void setHistorical(String historical) { this.historical = historical; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } /** * 主要是 創建 標簽這里需要一些技術。 * 現在 樣式 :首頁 上一頁 下一頁 尾頁 共 3 頁,6 條記錄。當前第 3 頁,分頁單位是 2 條記錄 * 期望樣式 :首頁 上一頁 ... 7 8 9 10 11 12 ... 下一頁 尾頁 共1234條 每頁顯示 10/23 */ @Override public int doStartTag() throws JspException { /* * 現在 樣式 :首頁 上一頁 下一頁 尾頁 共 3 頁,6 條記錄。當前第 3 頁,分頁單位是 2 條記錄 * 期望樣式 :首頁 上一頁 ... 7 8 9 10 11 12 ... 下一頁 尾頁 共1234條 每頁顯示 10/23 * * 修改點1: * 需要在 上一頁 和 下一頁中間加入一些內容。數字,如果頁數大於5就有必要隱藏一些數據,如果頁數小於5就展示所有信息。 * * 修改點2: * 共 3 頁,6 條記錄。當前第 3 頁,分頁單位是 2 條記錄 * 共1234條 每頁顯示 10/23 */ JspWriter out = this.pageContext.getOut();//select * from user_tb where username like '%~%'; if(pageSize==0||count==0){ try { out.println("%>_<%,查找時,未獲得數據喲~~~。【請更換查找條件 O(∩_∩)O ~~~】"); } catch (IOException e) { System.out.println("未獲得數據,輸出標簽時,出現異常"); e.printStackTrace(); } return this.EVAL_PAGE; }else{ int totalPage = count%pageSize==0?count/pageSize:count/pageSize+1; if(currentPage<=1){ currentPage = 1; } if(currentPage>=totalPage){ currentPage = totalPage; } //<a href="BookServlet.do?page=3&historical=yes&method=somehow" >超級鏈接</a> //string pattern1 = wo de ming zi jiao {0} nian ling shi {1}; // string str1 = messageFormat.format(pattern1,"lifei",23); //System.out.println(str1); ---> wo de ming zi jiao lifei nian ling shi 23; String linkPattern = "<a href=\"{0}?page={1}&historical={3}&method={4}\">{2}</a>"; String first = MessageFormat.format(linkPattern, url,1,"首頁",historical,method); String pre = MessageFormat.format(linkPattern, url,currentPage-1,"上一頁",historical,method); String next = MessageFormat.format(linkPattern,url,currentPage+1,"下一頁",historical,method); String last = MessageFormat.format(linkPattern, url,totalPage,"尾頁",historical,method); if(currentPage<=1){ first = "首頁"; pre = "上一頁"; } if(currentPage>=totalPage){ next = "下一頁"; last = "尾頁"; } /* * 共 3 頁,6 條記錄。當前第 3 頁,分頁單位是 2 條記錄 * 共1234條 每頁顯示 10/23 */ String htmlString = "{0} {1} {7}{2} {3} 共 {4} 條 每頁顯示 {5}/{6}"; String middle = getMiddleNumber(totalPage,currentPage); //System.out.println(middle); int showPageSize=0; if(currentPage!=totalPage){ showPageSize = pageSize; }else{ showPageSize = count-pageSize*(totalPage-1); } //System.out.println(showPageSize); htmlString = MessageFormat.format(htmlString, first,pre,next,last,count,showPageSize,count,middle); //System.out.println(htmlString); try { out.println(htmlString); } catch (IOException e) { System.out.println("輸出標簽時,出現異常"); e.printStackTrace(); } return this.EVAL_PAGE; } } /** * 拼接中間的那對數字的代碼 * @param totalPage * @param currentPage * @return */ private String getMiddleNumber(int totalPage,int currentPage) { //System.out.println(currentPage); // TODO 這也是個bug 首頁 上一頁 1 下一頁 尾頁 共 1 條 每頁顯示 2/1 當只有一個 用戶的時候。 // 如果真的老板喪心病狂,把 用戶 一個一個 都刪了,這就會出問題, // 如果 此時 有人直接 動了 數據庫,刪除了當前用戶,根據 session他仍然能夠 登錄,這也是個 bug。 // TODO //<a href="BookServlet.do?page=3&historical=yes&method=somehow" >超級鏈接</a> String linkPattern = "<a href=\"{0}?page={1}&historical={3}&method={4}\">{2}</a>"; String[] strings = null; StringBuffer sb=null; if(totalPage<=0){ //如果條目數<=0的話 //如果系統能夠登錄,只少有一個 用戶,那么就不用做,為0判斷。 System.out.println("沒有記錄可以被顯示"); }else{// 否則 count一定有值 //否則count 一定大於0. if(totalPage>5){ strings = new String[5]; }else{ strings = new String[totalPage]; } String string=null; //if(totalPage<=5){//1-5 //string =MessageFormat.format(linkPattern,url,count,count,historical,method); //strings[count-1]=string; int times = 0; if(totalPage<=5){ times=totalPage; }else { times=5; } if(totalPage<=5){//1,2,3,4,5 for(int i=1;i<=times;i++){ if(i==currentPage){ string = i+""; strings[i-1]=string; //System.out.println(string); }else{ string = MessageFormat.format(linkPattern, url,i,i,historical,method); strings[i-1]=string; string=null; } } }else{//6,7,8…… int middle=0; if(currentPage<3){ middle=3; }else if(currentPage+2>totalPage){ middle = totalPage-2; }else { middle = currentPage; } for(int i=middle-2,j=0;i<=middle+2;i++,j++){ if(i!=currentPage){ string = MessageFormat.format(linkPattern, url,i,i,historical,method); //System.out.println(i); //System.out.println(j);//調皮的bug,我不輸出你,你都不老老實實執行!!!,這應該是 歷史上第三次了,之前事件監聽里面有一回。 //System.out.println(string); //System.out.println(strings.length); strings[j] = string; string = null; }else { string = i+""; strings[j]=string; string=null; } } } //} /*else if(totalPage>5){ //如果>5的話,是不是要顯示中間的五個 //首頁 上頁 2 3 4 5 6 下頁 尾頁 *** int middle=0; if(currentPage<3){ middle=3; }else if(currentPage+2>totalPage){ middle = totalPage-2; }else { middle = currentPage; } for(int i=middle-2;i<=middle+2;i++){ string = MessageFormat.format(linkPattern, url,i,i,historical,method); strings[i-1] = string; string = null; } }*/ sb = new StringBuffer(); for(int i=0;i<strings.length;i++){ sb.append(strings[i]); sb.append(" "); } if(totalPage>5){ if(currentPage>3){ sb.insert(0, "……"); } if(currentPage+2<totalPage){ sb.append("……"); } } } return sb.toString(); } }
