JSP第七篇【簡單標籤、應用、DynamicAttribute接口】

爲何要用到簡單標籤?

上一篇博客中我已經講解了傳統標籤,想要開發自定義標籤,大多數狀況下都要重寫doStartTag(),doAfterBody()和doEndTag()方法,而且還要知道SKIP_BODY,EVAL_BODY等等的變量表明着什麼,在什麼方法中使用。這樣實在是太麻煩了!javascript

所以,爲了簡化標籤開發的複雜度,在JSP 2.0中定義了一個更爲簡單、便於編寫和調用的SimpleTag接口來實現標籤的功能。php

通常來講,實現了SimpeTag接口的標籤稱之爲簡單標籤html

SimpleTag接口

  • 首先咱們來看一下它的源碼吧
public interface SimpleTag extends JspTag {
        void doTag() throws JspException, IOException;

        void setParent(JspTag var1);

        JspTag getParent();

        void setJspContext(JspContext var1);

        void setJspBody(JspFragment var1);
    }
  • setParent()和getParent()方法就很少說了,咱們來看一下剩下的3個方法
void doTag() throws JspException, IOException;

        void setJspContext(JspContext var1);

        void setJspBody(JspFragment var1);
  • 明顯地:
    • doTag()就是咱們要寫代碼處理邏輯地方
    • setJspContext(JspContext var1)是將PageContext對象傳遞給標籤處理器類(PageContext是JspContext的子類)
    • setJspBody(JspFragment var1)把表明標籤體的JspFragment對象傳遞給標籤處理器對象

快速入門

  • 通常地,咱們作開發都是繼承SimpleTagSupport類(該類實現了SimpleTag)來編寫自定義標籤
  • 下面咱們就來個快速入門吧
  • 目標:傳入字符串格式就能夠顯示想要的格式日期,對比以前傳統標籤的,看有什麼不一樣之處java

  • 標籤處理器類:數組

public class Demo1 extends SimpleTagSupport {


        String format = null;

        @Override
        public void doTag() throws JspException, IOException {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);

            this.getJspContext().getOut().write(simpleDateFormat.format(new Date()));
        }

        public String getFormat() {
            return format;
        }

        public void setFormat(String format) {
            this.format = format;
        }
    }
  • tld文件:
<tag>
        <name>formatDate</name>
        <tag-class>tag.Demo1</tag-class>
        <body-content>tagdependent</body-content>
        <attribute>
            <name>format</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
  • 效果:

  • 簡單標籤的好處就是不用去理會doStartTag、doEndTag、SKIP_BODY以及一系列的方法和屬性!
  • 簡單標籤一個doTag()方法走天下!

SimpleTagSupport類的執行順序:

  • ①WEB容器調用標籤處理器對象的setJspContext方法,將表明JSP頁面的pageContext對象傳遞給標籤處理器對象
  • ②WEB容器調用標籤處理器對象的setParent方法,將父標籤處理器對象傳遞給這個標籤處理器對象。【注意,只有在標籤存在父標籤的狀況下,WEB容器纔會調用這個方法】
  • ③若是調用標籤時設置了屬性,容器將調用每一個屬性對應的setter方法把屬性值傳遞給標籤處理器對象。若是標籤的屬性值是EL表達式或腳本表達式,則WEB容器首先計算表達式的值,而後把值傳遞給標籤處理器對象。
  • ④若是簡單標籤有標籤體,容器將調用setJspBody方法把表明標籤體的JspFragment對象傳遞進來
  • ⑤執行標籤時:容器調用標籤處理器的doTag()方法,開發人員在方法體內經過操做JspFragment對象,就能夠實現是否執行、迭代、修改標籤體的目的。

深刻簡單標籤

在咱們講解傳統標籤的時候,配合着SKIP_BODY、SKIP_PAGE等變量能夠實現以下的功能:瀏覽器

  1. 控制jsp頁面某一部份內容(標籤體)是否執行
  2. 控制整個jsp頁面是否執行
  3. 控制jsp頁面內容重複執行
  4. 修改jsp頁面內容輸出

  • 簡單標籤可沒有這些變量呀,那它怎麼才能實現上面那些功能呢?markdown

  • 在doTag方法中能夠拋出javax.servlet.jsp.SkipPageException異常,用於通知WEB容器再也不執行JSP頁面中位於結束標記後面的內容,這等效於在傳統標籤的doEndTag方法中返回Tag.SKIP_PAGE常量的狀況,咱們來測試一下,在上面例子的代碼中添加app

throw new SkipPageException();
  • 效果:

  • 至於其餘的功能下面會講到

帶標籤體的簡單標籤

  • SimpleTagSupport也能夠帶標籤體,可是處理方法和傳統標籤徹底不一樣less

    • 傳統標籤是這樣子的:將標籤體的內容經過setBodyContent()注入到BodyContent對象中。
    • 簡單標籤是這樣子的:經過JspFragment對象實現!
  • 咱們來看一下JspFragment對象的源碼吧jsp

 public abstract class JspFragment { public JspFragment() { } public abstract void invoke(Writer var1) throws JspException, IOException; public abstract JspContext getJspContext(); } 

JspFragment對象十分簡單,重要的只有invoke(Writer var1)方法(獲取JspContext對象並不重要,在標籤描述起上就能夠獲取到了)

public abstract void invoke(java.io.Writer out) :

  • 用於執行JspFragment對象所表明的JSP代碼片斷
  • 參數out用於指定將JspFragment對象的執行結果寫入到哪一個輸出流對象中,若是傳遞給參數out的值爲null,則將執行結果寫入到JspContext.getOut()方法返回的輸出流對象中。(簡而言之,能夠理解爲寫給瀏覽器)

  • 下面是標籤處理器類的代碼
public class Demo1 extends SimpleTagSupport {
        @Override
        public void doTag() throws JspException, IOException {

            //獲得表明標籤體的對象
            JspFragment jspFragment = getJspBody();

            //invoke方法接收的是一個Writer,若是爲null,就表明着JspWriter(),將標籤體的數據寫給瀏覽器!
            jspFragment.invoke(null);

        }
    }
  • 效果:

  • 既然標籤體的內容是經過JspFragment對象的invoke()方法寫給瀏覽器的,那麼那麼那麼,我只要控制好invoke()方法,我想幹什麼就幹什麼!

  • 也就是說:

    • 不調用invoke()方法,標籤體內容就不會輸出到瀏覽器上
    • 重複調用invoke()方法,標籤體內容就會被重複執行
    • 若想在標籤處理器中修改標籤體內容,只需在調用invoke方法時指定一個可取出結果數據的輸出流對象(例如StringWriter),讓標籤體的執行結果輸出到該輸出流對象中,而後從該輸出流對象中取出數據進行修改後再輸出到目標設備,便可達到修改標籤體的目的
  • 來來來,咱們來試驗一下:

    • 不調用invoke()方法
    public void doTag() throws JspException, IOException {
    
            //獲得表明標籤體的對象
            JspFragment jspFragment = getJspBody();
    
            //jspFragment.invoke(null);
    
        }
    • 標籤體的內容沒有輸出

    • 調用兩次invoke()方法

    public void doTag() throws JspException, IOException {
    
            //獲得表明標籤體的對象
            JspFragment jspFragment = getJspBody();
    
            jspFragment.invoke(null);
            jspFragment.invoke(null);
    
        }
    • 標籤體的內容被輸出了兩次
    • invoke()方法指定別的輸出流(StringWriter),將標籤體的內容寫到流對象中,再經過流對象把數據取出來,達到修改的目的。
    //獲得表明標籤體的對象
            JspFragment jspFragment = getJspBody();
    
            //建立能夠存儲字符串的Writer對象
            StringWriter stringWriter = new StringWriter();
    
            //invoke()方法把標籤體的數據都寫給流對象中
            jspFragment.invoke(stringWriter);
    
            //把流對象的數據取出來,流對象的數據就是標籤體的內容
            String value = stringWriter.toString();
    
            //將數據改爲是大寫的,寫到瀏覽器中
            getJspContext().getOut().write(value.toUpperCase());
    • 標籤體的內容被改爲了大寫!

咱們能夠發現,傳統標籤能完成的功能,簡單標籤均可以完成,而且更爲簡單!


自定義標籤的應用

既然咱們學了簡單標籤,咱們就用簡單標籤來作開發吧!

防盜鏈

在講解request對象的時候,咱們講解過怎麼實現防盜鏈的功能。如今咱們使用標籤來進行防盜鏈

模擬下場景:1.jsp頁面是海賊王資源,2.jsp頁面提示非法盜鏈,index1.jsp是個人首頁。別人想要看個人海賊王資源,就必須經過個人首頁點進去看,不然就是非法盜鏈!

  • 標籤處理器的代碼
@Override
    public void doTag() throws JspException, IOException {

        //若是想要作成更加靈活的,就把站點設置和資源設置成標籤屬性傳遞進來!

        //等會咱們要獲取獲得request對象,須要使用到JspContext的子類PageContext
        PageContext pageContext = (PageContext) this.getJspContext();

        //獲取request對象
        HttpServletRequest httpServletRequest = (HttpServletRequest) pageContext.getRequest();

        //獲取到referer
        String referer = httpServletRequest.getHeader("Referer");

        //獲取到response對象,等會若是是非法盜鏈,就重定向別的頁面上
        HttpServletResponse httpServletResponse = (HttpServletResponse) pageContext.getResponse();

        //非法盜鏈!
        if (referer == null || !referer.startsWith("http://localhost:8080/zhongfucheng")) {

            //2.jsp提示了非法盜鏈!
            httpServletResponse.sendRedirect("/zhongfucheng/2.jsp");

            //不執行頁面下面的內容了,保護頁面
            throw new SkipPageException();
        }
    }
  • 1.jsp代碼:
<zhongfucheng:Referer/>
    <html>
    <head>
        <title></title>
    </head>
    <body>

    海賊王最新資源

    </body>
    </html>
  • index1.jsp代碼
<h1>這是首頁!</h1>
    <a href="${pageContext.request.contextPath}/1.jsp"> 海賊王最新資源</a>
  • 2.jsp代碼
<body>
    你是非法盜鏈的!!!!!!
    </body>
  • 第一次我是直接訪問1.jsp,Referer是爲空的,因此是非法盜鏈。第二次我是經過從首頁點進去看的,因此能夠訪問1.jsp。效果圖:


if標籤

在JSTL中,咱們已經使用過了<c:if/>標籤了,如今咱們學習了自定義標籤,能夠開發相似於JSTL的if標籤了!

既然是if標籤,那麼就須要編寫帶屬性和帶標籤體的標籤(須要判斷是true仍是false呀!,經過判斷是否爲真值來決定是否執行標籤體的內容)

  • 標籤處理器代碼
public class Demo1 extends SimpleTagSupport {

        //定義一個Boolean類型的變量
        boolean test ;

        @Override
        public void doTag() throws JspException, IOException {

            //獲取到表明標籤體內容的對象
            JspFragment jspFragment = this.getJspBody();

            //若是爲真值才執行標籤體的內容
            if (test == true) {
                jspFragment.invoke(null);
            }
        }

        public boolean isTest() {
            return test;
        }

        public void setTest(boolean test) {
            this.test = test;
        }
    }
  • tld文件的代碼
<tag>
        <name>if</name>
        <tag-class> tag.Demo1</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>test</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
  • 原本就沒有user這個域對象屬性,因此user就是爲null

  • 將user改爲不爲null,瀏覽器就沒有輸出了


forEach標籤

forEach標籤最基本的功能:遍歷集合、數組

  • 首先,我先寫一個能夠遍歷List集合的標籤,可能咱們會這樣設計
public class Demo2 extends SimpleTagSupport {

    //遍歷的是List集合,因而標籤的屬性就爲List
    private List items;

    //遍歷出來的對象就用Object存着,由於咱們不知道List集合保存的是什麼元素
    private Object var;


    @Override
    public void doTag() throws JspException, IOException {

        //獲取到迭代器
        Iterator iterator = items.iterator();

        //遍歷集合
        while (iterator.hasNext()) {

            //獲取到集合的元素
            var = iterator.next();

            //.....var屬性表明的就是集合的元素,如今問題來了,好像在標籤體內沒法獲取到這個對象....
            //作到這裏完成不下去了....
        }
    }

    public void setItems(List items) {
        this.items = items;
    }

    public void setVar(Object var) {
        this.var = var;
    }
}

上面的思路是正常的,可是作不下去!咱們換一個思路唄。上面的問題主要是在標籤體獲取不到被遍歷出來的對象

咱們這樣作:把var定義成String類型的,若是遍歷獲得對象了,就設置PageContext的屬性,var爲關鍵字,對象爲值。在標籤體用EL表達式搜索以var爲關鍵字的對象!每遍歷出一個對象,就執行一次標籤體!

  • 因而就有了如下的代碼!
public class Demo1 extends SimpleTagSupport {

    //遍歷的是List集合,定義List集合成員變量
    private List items;

    //以var爲關鍵字存儲到PageContext
    private String var;



    @Override
    public void doTag() throws JspException, IOException {

        //獲取到集合的迭代器
        Iterator iterator = items.iterator();

        //獲取到表明標籤體內容的對象
        JspFragment jspFragment = this.getJspBody();

        //遍歷集合
        while (iterator.hasNext()) {
            Object o = iterator.next();

            //把遍歷出來的對象存儲到page範圍中,關鍵字爲標籤的屬性var(在標籤體中使用EL表達式${var},就可以獲取到集合的對象了!)
            this.getJspContext().setAttribute(var, o);

            //每設置了一個屬性,我就執行標籤體
            jspFragment.invoke(null);
        }
    }

    public void setItems(List items) {
        this.items = items;
    }

    public void setVar(String var) {
        this.var = var;
    }
}
  • tld文件以下
<tag>
        <name>forEach</name>
        <tag-class>tag.Demo1</tag-class>
        <body-content>scriptless</body-content>
        <attribute>
            <name>var</name>
            <rtexprvalue>true</rtexprvalue>
            <!--字符串便可,不須要EL表達式的支持-->
            <required>false</required>
        </attribute>

        <attribute>
            <name>items</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
  • 測試的jsp代碼以下
<%
        List list = new ArrayList();
        list.add("zhongfucneng");
        list.add("1");
        list.add("2");
        list.add("3");

        request.setAttribute("list",list);
    %>
    <zhongfucheng:forEach items="${list}" var="str">

        ${str}

    </zhongfucheng:forEach>
  • 效果:

上面寫的僅僅可以遍歷List集合,作一個通用的forEach標籤麻煩的是在:不知道傳進來的是什麼類型的數組、什麼類型集合!,須要逐一去判斷

  • 咱們來嘗試着寫一下
//若是items是Collection類型的,就強轉爲Colletion
        if (items instanceof Collection) {
            collection = (Collection) items;
        }

        //若是itmes是Map類型的,那麼就強轉爲Map,再獲取到<Map.Entry<K, V>,這個是Set集合的!
        if (items instanceof Map) {
            Map map = (Map) items;
            collection = (Collection) map.entrySet();
        }

        //對象數組
        if (items instanceof Object[]) {
            Object[] objects = (Object[]) items;
            collection = Arrays.asList(objects);
        }

        //int[],Byte[],char[]等八大基本數據類型.....

還有int[],byte[],char[]等八大基本數據類型,這八大基本數據類型就不能用Arrays.asList()把引用傳進去了。由於JDK5之後會把引用自動裝箱成Interger[]、Byte[]等等,而不是獲取到數組的元素數據。

  • 測試代碼以下:
public static void main(String[] args) {

        int[] ints = new int[]{1, 2, 3};
        Object[] objects = new Object[]{"1", "2", "3"};

        if (objects instanceof Object[]) {
            Collection collection = Arrays.asList(objects);
            System.out.println(collection);
        }
        if (ints instanceof int[]) {

            Collection collection1 = Arrays.asList(ints);
            System.out.println(collection1);
        }
    }
  • 效果:

  • 對於八大基本類型數據咱們就能夠這樣幹
 if (items instanceof int[]) { int[] ints = (int[]) items; collection = new ArrayList(); for (int anInt : ints) { collection.add(anInt); } } //......這裏還要寫7個 
  • JSTL的forEach標籤相似就是這樣乾的

因爲JDK5的新特性,咱們又有另外的解決方案,Class對象可以判斷是否爲數組類,reflect反射包下Array類

  • 其實,不管Map集合、仍是任何類型的數組、均可以使用Colletion進行遍歷!。

  • 標籤處理器的代碼

public class Demo1 extends SimpleTagSupport {

    //遍歷的是未知的集合或數組,定義成Object
    private Object items;

    //每次被遍歷的對象存儲關鍵字
    private String var;

    //Colletion
    private Collection collection;

    //在WEB容器設置標籤的屬性的時候,判斷是什麼類型的數組和集合
    public void setItems(Object items) {
        this.items = items;

        //若是items是Collection類型的,就強轉爲Colletion
        if (items instanceof Collection) {
            collection = (Collection) items;
        }

        //若是itmes是Map類型的,那麼就強轉爲Map,再獲取到<Map.Entry<K, V>,這個是Set集合的!
        if (items instanceof Map) {
            Map map = (Map) items;
            collection = (Collection) map.entrySet();
        }

        //能夠這樣解決,Class對象判斷是不是一個數組類
        if (items.getClass().isArray()) {

            //建立Collection集合添加數組的元素!
            collection = new ArrayList();

            //再利用reflect包下的Array類獲取到該數組類的長度
            int len = Array.getLength(items);

            //遍歷並添加到集合中
            for (int i = 0; i < len; i++) {
                collection.add(Array.get(items, i));
            }
        }
    }

    public void setVar(String var) {
        this.var = var;
    }

   @Override
    public void doTag() throws JspException, IOException {

        //獲取到表明標籤體內容的對象
        JspFragment jspFragment = this.getJspBody();
        Iterator iterator = collection.iterator();


        //遍歷集合
        while (iterator.hasNext()) {
            Object o = iterator.next();

            //把遍歷出來的對象存儲到page範圍中(在標籤體中使用EL表達式${var},就可以獲取到集合的對象了!)
            this.getJspContext().setAttribute(var, o);

            jspFragment.invoke(null);
        }
    }
}
  • tld文件和上面是同樣的,下面是測試代碼
<% /*list集合*/ List list = new ArrayList(); list.add("zhongfucneng"); list.add("1"); list.add("2"); list.add("3"); request.setAttribute("list",list); /*基本數據類型數組*/ int[] ints = new int[]{1, 2, 3, 4, 5}; request.setAttribute("ints", ints); /*對象數組*/ Object[] objects = new Object[]{2, 3, 4, 5, 6}; request.setAttribute("objects", objects); /*map集合*/ Map map = new HashMap(); map.put("aa", "aa"); map.put("bb", "bb"); map.put("cc", "cc"); request.setAttribute("map",map); %> List集合: <zhongfucheng:forEach items="${list}" var="str"> ${str} </zhongfucheng:forEach> <hr> <hr> 基本數據類型數組: <zhongfucheng:forEach items="${ints}" var="i"> ${i} </zhongfucheng:forEach> <hr> <hr> 對象數組: <zhongfucheng:forEach items="${objects}" var="o"> ${o} </zhongfucheng:forEach> <hr> <hr> map集合: <zhongfucheng:forEach items="${map}" var="me"> ${me.key} = ${me.value} </zhongfucheng:forEach> 
  • 效果:


HTML轉義標籤

要開發這個標籤就很簡單了,只要獲取到標籤體的內容,再經過通過方法轉義下標籤體內容,輸出給瀏覽器便可

  • 標籤處理器代碼:
public class Demo1 extends SimpleTagSupport {



   @Override
    public void doTag() throws JspException, IOException {

       //獲取到標籤體的內容再修改
       StringWriter stringWriter = new StringWriter();
       JspFragment jspFragment = this.getJspBody();
       jspFragment.invoke(stringWriter);
       String content = stringWriter.toString();

       //通過filter()轉義,該方法在Tomcat能夠找到
       content = filter(content);

       //再把轉義後的內容輸出給瀏覽器
       this.getJspContext().getOut().write(content);


    }

    private 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());
    }
}
  • 測試代碼
<zhongfucheng:filter><a href="2.jsp">你好啊</a> </zhongfucheng:filter>

    <br>
    <a href="2.jsp">你好啊
  • 效果:


if else標籤

在JSTL中並無if else的標籤,JSTL給予咱們的是choose,when,otherwise標籤,如今咱們模仿choose,when,otherwise開發標籤

思路:when標籤有個test屬性,但otherwise怎麼判斷標籤體是執行仍是不執行呢?這時就須要choose標籤的支持了!choose標籤默認定義一個Boolean值爲false,。當when標籤體被執行了,就把Boolean值變成true,只要Boolean值爲false就執行otherwise標籤體的內容。

看程序就容易理解上面那句話了:

  • choose標籤處理器
public class Choose extends SimpleTagSupport {

        private boolean flag;

        @Override
        public void doTag() throws JspException, IOException {

            this.getJspBody().invoke(null);
        }

        public boolean isFlag() {
            return flag;
        }

        public void setFlag(boolean flag) {
            this.flag = flag;
        }
    }
  • When標籤處理器
public class When extends SimpleTagSupport {

        private boolean test ;

        @Override
        public void doTag() throws JspException, IOException {


            Choose choose = (Choose) this.getParent();

            //若是test爲true和flag爲false,那麼執行該標籤體
            if (test == true && choose.isFlag() == false) {

                this.getJspBody().invoke(null);

                //修改父標籤的flag
                choose.setFlag(true);
            }

        }
        public void setTest(boolean test) {
            this.test = test;
        }
    }
  • OtherWise標籤處理器
 public class OtherWise extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { Choose choose = (Choose) this.getParent(); //若是父標籤的flag爲false,就執行標籤體(若是when標籤沒執行,flag值就不會被修改!when標籤沒執行,就應該執行otherwise標籤!) if (choose.isFlag() == false) { getJspBody().invoke(null); //改父標籤的flag爲false choose.setFlag(true); } } } 
  • 測試代碼:
<zhongfucheng:choose>
        <zhongfucheng:when test="${user!=null}">
            user爲空
        </zhongfucheng:when>

        <zhongfucheng:otherwise>
            user不爲空
        </zhongfucheng:otherwise>

    </zhongfucheng:choose>
  • 效果:


DynamicAttribute接口

此接口的主要功能是用於完成動態屬性的設置!前面咱們講解屬性標籤的時候,屬性都是寫多少個,用多少個的。如今若是我但願屬性能夠動態的增長,只須要在標籤處理器類中實現DynamicAttribute接口便可!

如今我要開發一個動態加法的標籤

  • 標籤處理器
public class Demo1 extends SimpleTagSupport implements DynamicAttributes {

        //既然有動態屬性和動態的值,那麼咱們就用一個Map集合存儲(1-1對應的關係),作的加法運算,值爲Double類型的。
        Map<String, Double> map = new HashMap<>();

        @Override
        public void doTag() throws JspException, IOException {

            //定義一個sum變量用於計算總值
            double sum = 0.0;

            //獲取到Map集合的數據
            Iterator iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Double> entry = (Map.Entry<String, Double>) iterator.next();

                sum += entry.getValue();
            }

            //向瀏覽器輸出總和是多少
            this.getJspContext().getOut().write(String.valueOf(sum));
        }


        //對於這個要實現的方法,咱們只要關注第2個參數和第3個參數便可
        //第二個參數表示的是動態屬性的名稱,第三個參數表示的是動態屬性的值
        @Override
        public void setDynamicAttribute(String s, String localName, Object value) throws JspException {

            //將動態屬性的名字和值加到Map集合中
            map.put(localName, Double.valueOf(Float.valueOf(value.toString())));
        }
    }
  • tld文件,注意要把dynamic-attribute設置爲true
 <tag> <name>dynamicAttribute</name> <tag-class> tag.Demo1</tag-class> <body-content> empty</body-content> <!--這個必需要設置爲true--> <dynamic-attributes>true</dynamic-attributes> </tag> 
  • 測試代碼
<zhongfucheng:dynamicAttribute num="1.1" num2="2.2" num3="1"/>
  • 效果,double在運算的時候會丟失精度的,如今只是測驗下動態屬性,這裏就不詳細說了!

開發自定義函數

至於怎麼開發自定義函數,在EL表達式的博客中有

相關文章
相關標籤/搜索