posts - 78, comments - 34, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

                   除了JavaMail今日是JavaWeb部分的最后一天了,還有三天的時間是做個小項目。將之前學(xué)習(xí)的所有知識串起來,準備迎接高級部分。嘿嘿!終于到了高級部分!

                   今日主要內(nèi)容是JSP自定義標簽與JSTL,之前有使用過JSTL,十分的方便,還有EL。也有學(xué)過自定義EL函數(shù),但個人感覺EL自定義函數(shù)沒有JSP的自定義標簽有趣。

          一、JSP自定義標簽

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

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

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

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

          3.        WEB應(yīng)用中部署和安裝自定義標簽庫。

          4.        JSP頁面中導(dǎo)入和使用自定義標簽。

          在以前的JSP頁面編寫中,我們有使用過“<cc:if test=”邏輯表達方式”>”和<cc:froEach var=”變量” items=”集合、列表、數(shù)組”>。下面我們就來實現(xiàn)與這兩個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()”當自定義標簽開始被執(zhí)行時,JSP引擎會調(diào)此方法。在此方法中可以“Tag.EVAL_BODY_INCLUDE”告訴JSP引擎繼續(xù)向下執(zhí)行標簽體中的內(nèi)容,如果返回“Tag.SKIP_BODYJSP引擎將不執(zhí)行標簽體中的內(nèi)容。

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

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

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

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

          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>”設(shè)置tld描述文件的URIURI用于在JSP頁面中引入此tld文件。

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

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

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

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

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

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

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

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

           

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

          <%@ 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方法即可實現(xiàn)forEach

              @Override

              public void doTag() throws JspException, IOException {

                 Iterator iter = this.items.iterator();

                 while (iter.hasNext()) {

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

                     this.getJspContext()

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

                     // 調(diào)用執(zhí)行標簽體,需要一個輸出流參數(shù),

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

                     this.getJspBody().invoke(null);

                 }

              }

          }

           

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

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

          MyEl.tld,添加如下內(nèi)容:

              <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>”指定標簽體內(nèi)為非腳本代碼。

           

          Index.jsp添加如下內(nèi)容:

          <%

                 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自定義標簽高級部分:

          修改標簽內(nèi)容的標簽<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(new FileReader(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 {

                 // 調(diào)用子標簽,并將輸出流傳遞進去。

                 CharArrayWriter caw = new CharArrayWriter(); 

                 this.getJspBody().invoke(caw);

                 //這里之所以要寫義一個輸出流,是為了實現(xiàn)Html字符的轉(zhuǎn)換

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

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

              }

             

              // Html字符轉(zhuǎn)換

              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());

              }

          }

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

                   二、JSTL標簽

                   1.jstl標簽分為:

                   核心標簽庫

          國際化標簽

          數(shù)據(jù)庫標簽

          XML標簽

          JSTL函數(shù)

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

           

                   2.jstl常用的標簽:

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

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

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

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

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

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

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

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

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

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

                

                   OK,上面是常用的標簽,使用方法去查手冊吧!東西太多了。老方今天特別提到一個標簽,是佟老師特別指出的。它在Structs中使用較多——C:check permission

           

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

           

                   OK,明天就要老方就開始編寫一個將JavaSeb基礎(chǔ)部分的所有內(nèi)容融會到一起的WEB應(yīng)用用例。估計使用1天多點的時間。然后同學(xué)們有近兩天的個人實現(xiàn)時間。大家對此都十分期待!終于應(yīng)用這段時間所學(xué)的知識,寫個像樣的東西出來。

           

                   加油!


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 灵寿县| 黎平县| 扎囊县| 扎兰屯市| 五指山市| 屏东县| 班戈县| 武威市| 柳州市| 清河县| 兴业县| 康保县| 开封市| 哈尔滨市| 榕江县| 灵武市| 肇源县| 栾川县| 榆林市| 拉萨市| 桃园县| 清河县| 陕西省| 北票市| 车险| 五寨县| 石柱| 蒲城县| 古田县| 达拉特旗| 沙雅县| 开化县| 收藏| 美姑县| 濮阳市| 客服| 青岛市| 临夏县| 招远市| 边坝县| 察哈|