Jstl自定義標簽及其生命周期、屬性標簽、及其讀取文本練習、JspFragment輸出標簽體(2)

Jstl自定義標簽及其生命周期、屬性標簽、及其讀取文本練習、JspFragment輸出標簽體。

什麼是自定義標簽?
這裡寫圖片描述

這裡寫圖片描述

SimlpeTagSuPPort類的生命周期:
1.當jsp容器遇到自定義標簽時。jsp容器會調用標簽處理類的默認構造方法來建立一個標簽處理類的實例。必須為每個標簽都創建一個新的實例。
2.實例創建後,jsp容器會調用setJspContext()方法。並以一個JspContext實例提供上下文信息。如果是一個嵌套標簽,還講調用setParent()方法。
3.然後容器會調用該標簽中所定義的每個屬性的set方法,這樣標簽處理類實例就已經初始化完成瞭。
4.接著就由容器調用setJspBody()方法。將該標簽的主題設置為JspFragment實例。如果標簽主題是空的,則將null值傳到setJspBody().JspFragment實例代表標簽主題片段的引用。
5.接下來,由容器調用doTag()方法標簽要實現的所有邏輯、循環、主體賦值等都在該方法中發生。
6.在doTag()方法返回後,標簽處理類中所有的變量都是同步的。

如何創建自定義標簽?
1、寫一個標簽處理類,實現SimpleTag接口方法
2、建議在WEB-INF下配置文件tld文件
3、在jsp中taglib導入標簽庫描述文件,使用即可

HelloSimpleTag

package com.safly;
import java.io.IOException;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class HelloSimpleTag implements SimpleTag {
    public void doTag() throws JspException, IOException {
        System.out.println("doTag");
    }
    public JspTag getParent() {
        System.out.println("getParent");
        return null;
    }
    public void setJspBody(JspFragment jspBody) {
        System.out.println("setJspBody");
    }
    public void setJspContext(JspContext pc) {
        System.out.println("setJspContext");
    }
    public void setParent(JspTag parent) {
        System.out.println("setParent");
    }
}

mytld.tld




  MyTag 1.0 core library
  MyTag core
  1.0

  safly
  https://www.safly.com/mytld/core

  
    hello
    com.safly.HelloSimpleTag
    empty
  

mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@taglib uri="https://www.safly.com/mytld/core" prefix="safly"%>

<!– //prefix可用其他,但是相對應 –>

這裡寫圖片描述

標簽處理器可以做哪些操作呢?
通過jsp引擎調用,把代表jsp頁面的pageContext對象傳入,由於pageContext可以獲取jsp頁面其他的8個隱含對象,所以凡是jsp頁面可以做的,標簽處理器都可以做

還是上例中mytld.tld、mytag.jsp不過變化
HelloSimpleTag 做如下修改

package com.safly;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;

public class HelloSimpleTag implements SimpleTag {

    // 標簽體邏輯實際編寫到該方法中
        public void doTag() throws JspException, IOException {
            System.out.println("doTag");
            pageContext.getOut().println("helloworld");
            HttpServletRequest request = (HttpServletRequest) pageContext
                    .getRequest();
            pageContext.getOut().print("Hello" + request.getParameter("name"));
        }
        public JspTag getParent() {
            System.out.println("getParent");
            return null;
        }
        public void setJspBody(JspFragment jspBody) {
            System.out.println("setJspBody");
        }
        private PageContext pageContext;
        // jsp引擎調用,把代表jsp頁面的pagecontext對象傳入
        public void setJspContext(JspContext pc) {
            System.out.println("setJspContext");
            System.out.println(pc instanceof PageContext);
            this.pageContext = (PageContext) pc;
        }
        public void setParent(JspTag parent) {
            System.out.println("setParent");
        }

}

這裡寫圖片描述

屬性標簽
1.先在標簽處理類中定義setter方法,建議屬性都設置為String類型
2.在tld文件中來描述屬性vcD4NCjxwPm15dGxkLnRsZDwvcD4NCjxwcmUgY2xhc3M9″brush:sql;”>

MyTag 1.0 core library
MyTag core
1.0

safly
https://www.safly.com/mytag/core

hello
com.safly.HelloSimpleTag
empty

value
true

true

count
true

false

mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@taglib uri="https://www.safly.com/mytag/core" prefix="safly"%>

HelloSimpleTag

package com.safly;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class HelloSimpleTag implements SimpleTag {
//建議把所有的屬性定義成String類型
    private String value;
    private String count;
    public void setValue(String value) {
        this.value = value;
    }
    public void setCount(String count) {
        this.count = count;
    }
    // 標簽體邏輯實際編寫到該方法中
    public void doTag() throws JspException, IOException {
        System.out.println("doTag");
        JspWriter out = pageContext.getOut();
        int c = 0;
        c = Integer.parseInt(count);
        for (int i = 0; i < c; i++) {
            out.print(i + ":" + value);
            out.print("
");
        }
    }
    public JspTag getParent() {
        System.out.println("getParent");
        return null;
    }
    public void setJspBody(JspFragment jspBody) {
        System.out.println("setJspBody");
    }
    private PageContext pageContext;
    // jsp引擎調用,把代表jsp頁面的pagecontext對象傳入
    public void setJspContext(JspContext pc) {
        System.out.println("setJspContext");
        System.out.println(pc instanceof PageContext);
        this.pageContext = (PageContext) pc;
    }
    public void setParent(JspTag parent) {
        System.out.println("setParent");
    }
}

這裡寫圖片描述

輸出一個文件-利用自定義標簽

mytld.tld

     MyTag 1.0 core library
  MyTag core
  1.0

  safly
  https://www.safly.com/mytag/core

  
    readerFile
    com.safly.ReadFileTag
    empty


    
        src
        true
        
        true
   
  

mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@taglib uri="https://www.safly.com/mytag/core" prefix="safly"%>

ReadFileTag

package com.safly;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class ReadFileTag extends SimpleTagSupport {
    private String src;
    public void setSrc(String src){
        this.src = src;
    }
    @Override
    public void doTag() throws JspException, IOException {
        super.doTag();
        PageContext pageContext = (PageContext) getJspContext();
        InputStream in = pageContext.getServletContext().getResourceAsStream(src);
        BufferedReader reader = new BufferedReader(new InputStreamReader(in) );
        String str = null;
        while ((str=reader.readLine())!=null) {
            pageContext.getOut().write(str);
            pageContext.getOut().write("
");
        }
    }
}

看下目錄結構:
這裡寫圖片描述

瀏覽器輸出結果如下:
這裡寫圖片描述

利用JspFragment輸出標簽體的自定義標簽

 public void setJspBody(JspFragment jspBody) {
        System.out.println("setJspBody");
    }

它的實例對象代表JSP頁面中的一段符合JSP語法規范的JSP片段

WEB容器在處理簡單標簽的標簽體時,會把標簽體內容用一個JspFragment對象表示,並調用標簽處理器對象的setJspBody方法把JspFragment對象傳遞給標簽處理器對象。JspFragment類中隻定義瞭兩個方法,如下所示:

getJspContext方法用於返回代表調用頁面的JspContext對象.

public abstract voidinvoke(java.io.Writer out)

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

mytld.tld




     MyTag 1.0 core library
  MyTag core
  1.0

  safly
  https://www.safly.com/mytag/core

  
    testJspFragment
    com.safly.ReadFileTag
    scriptless
  

mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@taglib uri="https://www.safly.com/mytag/core" prefix="safly"%>

HelloWorld

ReadFileTag

package com.safly;
import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class ReadFileTag extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException, IOException {
        //自己定義的方法getJspBody
                JspFragment bodyContent= getJspBody();
                //參數為字符流,若為null則輸出getJspContext().getOut()到頁面上
                StringWriter sw = new StringWriter();
                bodyContent.invoke(sw);
                String content = sw.toString().toUpperCase();
                getJspContext().getOut().print(content);
    }
}

這裡寫圖片描述

帶標簽體的自定義標簽練習
mytld.tld




     MyTag 1.0 core library
  MyTag core
  1.0

  safly
  https://www.safly.com/mytag/core

 
    printUpper
    com.safly.PrintUpperTag
    scriptless

    
        time
        true
        true
    
  

  
    forEach
    com.safly.PrintUpperTag
    scriptless

    
        items
        true
        true
    

    
        var
        true
        true
    
   

Customer

package com.safly;

public class Customer {

    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Customer(Integer id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public Customer() {
        // TODO Auto-generated constructor stub
    }

}

PrintUpperTag

package com.safly;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Collection;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class PrintUpperTag extends SimpleTagSupport {
    private String time;

    public void setTime(String time) {
        this.time = time;
    }

    private Collectionitems;
    private String var;
    public void setItems(Collection items) {
        this.items = items;
    }
    public void setVar(String var) {
        this.var = var;
    }

    /////////////////////////////////////////
    @Override
    public void doTag() throws JspException, IOException {
        JspFragment bodyContent = getJspBody();
        StringWriter sw = new StringWriter();
        bodyContent.invoke(sw);

        String content = sw.toString();
        content = content.toUpperCase();

        int count = 1;
        try {
            count = Integer.parseInt(time);
        } catch (Exception e) {
        }
        for (int i = 0; i < count; i++) {
            getJspContext().getOut().print(content+"
");

        }

        if (items!=null) {
            for (Object obj: items) {
                getJspContext().setAttribute(var, obj);
                getJspBody().invoke(null);
            }
        }
    }
}

mytag.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%@page import="com.safly.Customer"%>
<%@taglib uri="https://www.safly.com/mytag/core" prefix="safly"%>
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>

 hello <% List customers = new ArrayList(); customers.add(new Customer(1,"AAA")); customers.add(new Customer(2,"BBB")); customers.add(new Customer(3,"CCC")); request.setAttribute("customers",customers); Map customerMap = new HashMap(); customerMap.put("a",customers.get(0)); customerMap.put("b",customers.get(1)); customerMap.put("c",customers.get(2)); request.setAttribute("customerMap",customerMap); %> ${pageScope.cust.key }–${cust.value.id }—${cust.value.name } ${pageScope.cust.id }–${cust.name }

瀏覽器輸入https://localhost:8080/day01/mytag.jsp
輸出結果如下:

&NBSP;HELLO
&NBSP;HELLO
&NBSP;HELLO
&NBSP;HELLO
&NBSP;HELLO
b--2---BBB c--3---CCC a--1---AAA -- 
1--AAA 2--BBB 3--CCC 

主要來說下

 
         ${pageScope.cust.id }--${cust.name }
      

如果傳遞給參數out的值為null,則將執行結果寫入到JspContext.getOut()方法返回的輸出流對象中。(簡而言之,可以理解為寫給瀏覽器)

在PrintUpperTag進行瞭如下操作:

if (items!=null) {
            for (Object obj: items) {
                getJspContext().setAttribute(var, obj);
                getJspBody().invoke(null);
            }
        }

然後在jsp頁面中進行獲取即可

發佈留言