posts - 11, comments - 0, trackbacks - 0, articles - 0

          傳統標簽VS常用簡單標簽

          Posted on 2011-03-14 22:44 HsiangYu 閱讀(601) 評論(0)  編輯  收藏 所屬分類: WEB

          一、JSP自定義標簽

          我們知道,JSP在被訪問時會被JSP引擎翻譯為Servlet程序,即JSP就是Servlet程序。我們可以在JSP中插入Java代碼,但是在JSP頁面中使用<%...%>嵌入JAVA代碼,使用頁面編寫起來十分混亂,更不利于以后的維護。因為,JSP自定義標簽可以優雅的解決這一問題。JSTL也正是SUN為些開發的一個標簽庫,接下來讓我們來編寫自己的自定義標簽。

          定義JSP自定義標簽,需要四個步驟:

          1.        編寫一個實現Tag接口的Java類(標簽處理器類),覆蓋其中的doStartTag方法,在doStartTag方法中編寫標簽的功能代碼。

          2.        編寫標簽庫描述符(tld)文件,在tld文件中對自定義標簽進行描述。

          3.        WEB應用中部署和安裝自定義標簽庫。

          4.        JSP頁面中導入和使用自定義標簽。

          在以前的JSP頁面編寫中,我們有使用過“<cc:if test=”邏輯表達方式”>”和<cc:froEach var=”變量” items=”集合、列表、數組”>。下面我們就來實現與這兩個JSP標簽類似功能的自定義JSP標簽。

          1.編寫<cc:if test=”…”>…</cc:forEach>自定義標簽:

          IfTag.java,標簽處理器:

          import javax.servlet.jsp.*;

          import javax.servlet.jsp.tagext.Tag;

           

          public class IfTag implements Tag {

              private boolean test;

              public void setTest(boolean test) {

                 this.test = test;

              }  

              public int doStartTag() throws JspException {

                 if(this.test)

                     return Tag.EVAL_BODY_INCLUDE;

                 return Tag.SKIP_BODY;

              }

              public int doEndTag() throws JspException {

                 // TODO Auto-generated method stub

                 return 0;

              }

              public Tag getParent() {

                 // TODO Auto-generated method stub

                 return null;

              }

              public void release() {

                 // TODO Auto-generated method stub

              }

              public void setPageContext(PageContext arg0) {

                 // TODO Auto-generated method stub

              }

              public void setParent(Tag arg0) {

                 // TODO Auto-generated method stub

              }

          }

          1.        private boolean test;”,這個成員名稱必須與JSP中自定義標簽的屬性名稱相同,JSP引擎會通過“setTest”方法,將屬性值傳遞過來。

          2.        doStartTag()”當自定義標簽開始被執行時,JSP引擎會調此方法。在此方法中可以“Tag.EVAL_BODY_INCLUDE”告訴JSP引擎繼續向下執行標簽體中的內容,如果返回“Tag.SKIP_BODYJSP引擎將不執行標簽體中的內容。

          3.        doEndTag()”當標簽體被執行完成后,會調用些方法。

          4.        getParent()”返回父標簽。

          5.        release()”,當標簽處理器被銷毀前會調用此方法,可以在此方法中釋放。但這個處理器被JSP引擎實例化后,一般不會被釋放而是保存在內存中,留以后用。服務器被關閉時,會被釋放。

          6.        setPageContext(PageContext arg0)”,JSP引擎將JSP頁面的運行環境,通過此方法傳遞給自定義標簽處理器。

          7.        setParent(Tag arg0)”,如果標簽有父標簽時,JSP引擎會將父標簽對象傳遞進來。

           

          MyEl.tld,自定義標簽描述文件。

          <?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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">

              <tlib-version>1.0</tlib-version>

              <short-name>SimpleTagLibrary</short-name>

              <uri>/SimpleTagLibrary</uri>

             

              <tag>

                 <name>myIf</name>

                 <tag-class>cn.itcast.cc.jsptag.IfTag</tag-class>

                 <body-content>JSP</body-content>

                 <attribute>

                     <name>test</name>

                     <required>true</required>

                     <rtexprvalue>true</rtexprvalue>

                 </attribute>

              </tag>

          </taglib>

          1.        tld文件在工程中的存放位置,與web.xml存位置相同。

          2.        <uri>”設置tld描述文件的URIURI用于在JSP頁面中引入此tld文件。

          3.        <tag>”定義一個自定義標簽。

          4.        <name>”自定義標簽名。

          5.        <tag-class>”自定義標簽處理器類,就是上邊編寫的類。

          6.        <body-content>”自定義標簽的標簽體內容。(也可以設置為“empty”等)

          7.        <attribute>”為自定義標簽添加一個屬性。

          8.        <name>”自定義標簽屬性名。

          9.        <required>true為必須指定此屬性,false此屬性可為空。

          10.     <rtexprvalue>”設置屬性為靜態的或是動態的。如果為false即靜態的,靜態的屬性值JSP引擎會將它自動轉換(必須是java8種基本數據類型),比如<cc:MyIf test=”122”>JSP引擎會自動將“123”轉換為整數型,所以處理器的類成員可以定義為int型。如果為true即動態的,如果設置為將類型設置為Object可以接收任意數據類型的屬性。

           

          Index.jsp,在JSP頁面中引入自定義標簽,并調用自定義標簽:

          <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

          <%@taglib prefix="cc" uri="/SimpleTagLibrary" %>

          <html>

            <head>

            </head>

           

            <body>

              <cc:myIf test="${2>1}">

                 自定義邏輯判斷標簽!

              </cc:myIf>

            </body>

          </html>

           

          2.編寫<cc:foEach var=”temp” items=”list”>…</cc:forEach>自定義標簽:

          forEahTag.java,繼承自SimpleTagSupport,這個簡單簡化了Tag接口的操作。

          import java.io.IOException;

          import java.util.*;

          import javax.servlet.jsp.JspException;

          import javax.servlet.jsp.tagext.SimpleTagSupport;

           

          public class forEahTag extends SimpleTagSupport {

           

              // 記錄 items="xxx中的list對象

              private List items;

              // 記錄 var="xxx"中的變量名稱

              private String var;

           

              public void setItems(List items) {

                 this.items = items;

              }

           

              public void setVar(String var) {

                 this.var = var;

              }

              // SimpleTagSupport簡化了Tag接口的操作,在此只需要覆蓋doTag方法即可實現forEach

              @Override

              public void doTag() throws JspException, IOException {

                 Iterator iter = this.items.iterator();

                 while (iter.hasNext()) {

                     // 將單個對象設置到Context域中,在JSP頁面中可以使用${var}獲取對象。

                     this.getJspContext()

                            .setAttribute(this.var, iter.next());

                     // 調用執行標簽體,需要一個輸出流參數,

                     // 設置為nullJSP引擎自動將其替換為this.getJspContext().getOut()

                     this.getJspBody().invoke(null);

                 }

              }

          }

           

          this.getJspBody()”返回JspFragment對象,JspFragment代表一個標簽體。JspFragment中不能包含JSP腳本元素。JspFragment.invoke就是調用標簽體。如果不調用此方法,就是忽略標簽體。

          forEach也可以使用實現TagSupport接口實現,當標簽體被調用時,首先會調用“doStartTag”方法(只會調用一次),可以在這個方法里先輸出第一個成員。然后執行標簽體,最后調用“doAfterBody”方法,它是重點。在這個方法里再輸出下一個成員然后判斷是不是到了list尾,如果到了list結尾則返回IterationTag. SKIP_BODY;。如果沒有到list結尾則返回IterationTag. EVAL_BODY_AGAIN;,繼續重復執行標簽體,實現對list的遍歷!

          MyEl.tld,添加如下內容:

              <tag>

                 <name>myForEach</name>

                 <tag-class>cn.itcast.cc.jsptag.forEahTag</tag-class>

                 <body-content>scriptless</body-content>

                 <attribute>

                     <name>var</name>

                     <required>true</required>

                     <rtexprvalue>true</rtexprvalue>

                 </attribute>

                 <attribute>

                     <name>items</name>

                     <required>true</required>

                     <rtexprvalue>true</rtexprvalue>

                 </attribute>

              </tag>

                   <body-content>scriptless</body-content>”指定標簽體內為非腳本代碼。

           

          Index.jsp添加如下內容:

          <%

                 List list = new ArrayList();

                 list.add("");

                 list.add("");

                 list.add("");

                 this.getServletContext().setAttribute("list",list);

               %>

              <cc:myForEach items="${list}var="temp">

                 ${temp }

              </cc:myForEach>

                   JSP頁面插入的代碼,是向List對象中插入成員,然后添加到ServletContext域中,${list}ServletContext域中獲取list對象。

           

                   3.JSP自定義標簽高級部分:

          修改標簽內容的標簽<cc:htmlFilter><cc:readFile>兩個標簽配合使用。

          ReadFileTag.java

          public class ReadFileTag extends SimpleTagSupport {

              // 記錄文件路徑

              private String src;

                

              public void setSrc(String src) {

                 this.src = src;

              }

           

              @Override

              public void doTag() throws JspException, IOException {

                 // 獲取到文件的全路徑

                 PageContext pc = (PageContext) this.getJspContext();

                 ServletContext sc = pc.getServletContext();

                 String file = sc.getRealPath(src);

                 // 使用字符緩沖流讀取文件

                 BufferedReader reader = new BufferedReader(newFileReader(file));

                 String line = null;

                 while((line = reader.readLine()) != null){

                     // 寫到輸出流

                     this.getJspContext().getOut().write(line + "\r\n");

                 }     

              }

          }

                   注意代碼中的寫到輸出流,這個輸出流是父標簽傳遞進來的輸出流。

           

          HtmlFilter.java

          public class HtmlFilter extends SimpleTagSupport {

           

              @Override

              public void doTag() throws JspException, IOException {

                 // 調用子標簽,并將輸出流傳遞進去。

                 CharArrayWriter caw = new CharArrayWriter(); 

                 this.getJspBody().invoke(caw);

                 //這里之所以要寫義一個輸出流,是為了實現Html字符的轉換

                 this.getJspContext().getOut().write(filter(caw.toString()));

                 System.out.println(caw.toString());

              }

             

              // Html字符轉換

              public static String filter(String message) {

           

                  if (message == null)

                      return (null);

           

                  char content[] = new char[message.length()];

                  message.getChars(0, message.length(), content, 0);

                  StringBuffer result = new StringBuffer(content.length + 50);

                  for (int i = 0; i < content.length; i++) {

                      switch (content[i]) {

                      case '<':

                          result.append("&lt;");

                          break;

                      case '>':

                          result.append("&gt;");

                          break;

                      case '&':

                          result.append("&amp;");

                          break;

                      case '"':

                          result.append("&quot;");

                          break;

                      default:

                          result.append(content[i]);

                      }

                  }

                  return (result.toString());

              }

          }

                   調用標簽體時,之所以傳遞一個自定義的輸出流。是因為,使用這個輸出流,獲取讀到的html文件的內容。然后將流中的html字符轉換后,再輸出到JSP頁面。

                   二、JSTL標簽

                   1.jstl標簽分為:

                   核心標簽庫

          國際化標簽

          數據庫標簽

          XML標簽

          JSTL函數

                   因為在JSP頁面中最好不要訪問數據庫和XML文件,這樣太不安全了而且程序邏輯混亂,所以就沒有講解這方面的使用。

           

                   2.jstl常用的標簽:

                   (1).<c:out>標簽:用于輸出一段文本內容到pageContext對象當前保存的“out”對象中。

                   (2). <c:set>標簽:用于設置各種Web域中的屬性,或者設置Web域中的java.util.Map類型的屬性對象或JavaBean類型的屬性對象的屬性。

                   (3). <c:remove>標簽:用于刪除各種Web域中的屬性。

                   (4). <c:catch>標簽:用于捕獲嵌套在標簽體中的內容拋出的異常。

                   (5). <c:if test=“”>標簽:可以構造簡單的“if-then”結構的條件表達式。

                   (6). <c:choose>標簽:用于指定多個條件選擇的組合邊界,它必須與<c:when><c:otherwise>標簽一起使用。

                   (7). <c:forEach>標簽:用于對一個集合對象中的元素進行循環迭代操作,或者按指定的次數重復迭代執行標簽體中的內容。

                   (8). <c:param>標簽:它可以嵌套在<c:import><c:url><c:redirect>標簽內,為這些標簽所使用的URL地址附加參數。此標簽自動進行URL編碼。

                   (9). <c:url>標簽:用于在JSP頁面中構造一個URL地址,其主要目的是實現URL重寫。還記得URL重寫是什么嗎?當session被禁用時,URL重寫就是為解決這一問題的!

                   (10). <c:redirect>標簽:用于將當前的訪問請求轉發或重定向到其他資源。

                

                   OK,上面是常用的標簽,使用方法去查手冊吧!東西太多了。再來一個標簽,Struts中使用較多——C:check permission

           

                   比如,一個管理頁面,有好多管理選項。但管理選項需要根據用戶的權限進行顯示,此時自定義一個檢查標簽,將User做為參數傳遞給標簽處理器。標簽處理器查看User的權限,然后確定是否執行標簽體。(標簽體中的內容為顯示相應的管理選項)

                

          主站蜘蛛池模板: 灌云县| 缙云县| 香格里拉县| 响水县| 安吉县| 红安县| 循化| 水富县| 鹤庆县| 鹤山市| 安化县| 崇阳县| 彭山县| 新野县| 湛江市| 漳州市| 丹阳市| 麻阳| 湄潭县| 修文县| 龙川县| 靖宇县| 定兴县| 绥江县| 宁津县| 融水| 临清市| 阿克苏市| 乌苏市| 滁州市| 米林县| 东莞市| 谢通门县| 红桥区| 集贤县| 太和县| 龙岩市| 长沙市| 仁化县| 崇左市| 德安县|