顯示具有 JSP 標籤的文章。 顯示所有文章
顯示具有 JSP 標籤的文章。 顯示所有文章

2015年10月13日 星期二

JSP賦值給 javascript

最近在公司寫了如下這一行
var xxx = <%=variable%>;

此時瀏覽器直器當機,看來是語法的錯誤,可是當時居然找不到,靜下心來後,發現原來要這樣子用

var xxx = '<%=variable%>';
        或是
var xxx = "<%=variable%>";

因為javascript原本就可以用單或雙引號,在此做個筆記,以免忘記

2015年9月28日 星期一

流程 (客製化JSP Tag 三)

 <<interface IterationTag>>
public static final int EVAL_BODY_AGAIN = 2;

<<interface Tag>>
public static final int SKIP_BODY = 0;
public static final int EVAL_BODY_INCLUDE = 1;
public static final int SKIP_PAGE = 5;
public static final int EVAL_PAGE = 6;

0、1給doStartTag()回傳
回傳0就調用doEndTag()
回傳1就調用doAfterBody()

0、2給doAfterBody()回傳
回傳0就調用doEndTag()
回傳2就調用自己,一直到回傳0為止

5、6給doEndTag()回傳
回傳5表示立即停止,忽略之後的頁面,但會將目前的輸出回傳到瀏覽器
回傳6表示正常結束


release():將資源全部釋放,修改後不重啟瀏覽器,過一下子就會直接調用


※SKIP_BODY、EVAL_BODY_INCLUDE

※AttrTag.java

public class AttrTag extends TagSupport {
    private String scope;
    private String content;
    // 這兩個屬性都給setter即可
    
@Override
public int doStartTag() throws JspException {
    System.out.println("doStartTag");
    Object value = null;
    if ("P".equals(scope)) {
        value = pageContext.getAttribute(content, PageContext.PAGE_SCOPE);
    }
    if ("R".equals(this.scope)) {
        value = pageContext.getAttribute(content, PageContext.REQUEST_SCOPE);
    }
    if ("S".equals(this.scope)) {
        value = pageContext.getAttribute(content, PageContext.SESSION_SCOPE);
    }
    if ("A".equals(this.scope)) {
        value = pageContext.getAttribute(content, PageContext.APPLICATION_SCOPE);
    }
    
    if (value == null) {
        return SKIP_BODY;
    } else {
        return EVAL_BODY_INCLUDE;
    }
    
}

※attr.tld

<tag>
    <name>displayScope</name>
    <tag-class>attr.AttrTag</tag-class>
    <body-content>JSP</body-content>
    <attribute>
        <name>scope</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
        <name>content</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>

body content變成JSP


※attr.jsp

<%
    String scope = "P";
    if ("P".equals(scope)) {
        pageContext.setAttribute("ooo", scope);
    } else if ("R".equals(scope)) {
        request.setAttribute("ooo", scope);
    } else if ("S".equals(scope)) {
        session.setAttribute("ooo", scope);
    } else if ("A".equals(scope)) {
        application.setAttribute("ooo", scope);
    }
%>
    
<bruce:displayScope scope="<%=scope%>" content="ooo">
    <h1>範圍:<%=scope%></h1>
    <h1>pageScope內容是${pageScope.ooo}</h1>
    <h2>requestScope內容是${requestScope.ooo}</h2>
    <h3>sessionScope內容是${sessionScope.ooo}</h3>
    <h4>applicationScope內容是${applicationScope.ooo}</h4>
</bruce:displayScope>

※如果scope不輸入PRSA其中一個,就會調用SKIP_BODY



※SKIP_BODY、EVAL_BODY_AGAIN


※jsp

<%
    List<String> list = new ArrayList<String>();
    list.add("A1");
    list.add("B2");
    list.add("C3");
    request.setAttribute("ooo", list);
%>
    
<bruce:iterate content="ooo" id="abc">
    ${abc}<br/>
</bruce:iterate>




※tld

<tag>
    <name>iterate</name>
    <tag-class>attr.AttrHaveContent2</tag-class>
    <body-content>JSP</body-content>
    <attribute>
        <name>content</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
        <name>id</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>




※java

public class AttrHaveContent extends TagSupport {
    private String content;
    private Iterator<?> it;
    
    public void setContent(String content) {
        this.content = content;
    }
    
    @Override
    public int doStartTag() throws JspException {
        System.out.println("doStartTag");
        Object value = pageContext.getAttribute(content, PageContext.REQUEST_SCOPE);
    
        System.out.println("value=" + value);
        if (value == null) {
            return SKIP_BODY;
        } else {
            List<?> x = ((List<?>) value);
            // Set<String> x = ((Map<String, Object>) value).keySet();
            // Collection<Object> x = ((Map<String, Object>) value).values();
            it = x.iterator();
    
            if (it.hasNext()) {
                pageContext.setAttribute(id, it.next());
                return EVAL_BODY_INCLUDE;
            }
            return SKIP_BODY;
        }
    }
    
    @Override
    public int doEndTag() throws JspException {
        System.out.println("doEndTag");
        return SKIP_PAGE;
    }
    
    @Override
    public int doAfterBody() throws JspException {
        System.out.println("doAfterBody");
    
        if (it.hasNext()) {
            pageContext.setAttribute(id, it.next());
            return EVAL_BODY_AGAIN;
        } else {
            return SKIP_BODY;
        }
    }
}

※TagSupport.java裡有個屬性是id,是protected,所以可以不用宣告id,但要用時還是要在tld裡定義



※setValue、getValues

List<?> x = ((List<?>) value);
for (int i = 0; i < x.size(); i++) {
    String s = (String) x.get(i);
    setValue(s.substring(1), "x");
}
    
enu = getValues();
if (enu.hasMoreElements()) {
    pageContext.setAttribute(id, enu.nextElement());
    return EVAL_BODY_INCLUDE;
}

※TagSupport還有個Hashtable叫values,但它是private,但有setValue和getValues可以塞進去,getValues回傳值是Enumeration,和Iterator很像

※doAfterBody也改成Enumeration就可以取到值了,取到的是setValue的Key值



※SKIP_PAGE、EVAL_PAGE

※jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="attrHaveContent" prefix="bruce"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head></head>
    <body>
        <bruce:endTagTest />
        ooo
    </body>
</html>



※web.xml

<jsp-config>
    <taglib>
        <taglib-uri>attrHaveContent</taglib-uri>
        <taglib-location>/WEB-INF/AttrHave.xml</taglib-location>
    </taglib>
</jsp-config>



※tld

<taglib version="2.1" 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 http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
    <tlib-version>1.0</tlib-version>
    <short-name>ht</short-name>
    
    <tag>
        <name>endTagTest</name>
        <tag-class>attr.AttrHaveContent</tag-class>
        <body-content>empty</body-content>
    </tag>
</taglib>



※java

public class AttrHaveContent extends TagSupport {
    @Override
    public int doEndTag() throws JspException {
        System.out.println("doEndTag");
    
        JspWriter out = this.pageContext.getOut();
        try {
            out.println("xxx");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return SKIP_PAGE;
    }
}

※回傳SKIP_PAGE時,不會印出ooo


繼承圖 (客製化JSP Tag 二)

※繼承圖



※各個Type的屬性、方法、建構子

<<JspTag>>

空的

<<Tag>>

static int EVAL_BODY_INCLUDE
static int EVAL_PAGE
static int SKIP_BODY
static int SKIP_PAGE

int   doEndTag()
int   doStartTag()
Tag   getParent()
void  release()
void  setPageContext(PageContext pc)    
void  setParent(Tag t)


<<SimpleTag>>

void doTag()
JspTag getParent()
void setJspBody(JspFragment jspBody)
void setJspContext(JspContext pc)
void setParent(JspTag parent)


SimpleTagSupport

實作SimpleTag的五個方法
static JspTag findAncestorWithClass(JspTag from, Class klass)
protected JspFragment getJspBody()
protected JspContext  getJspContext()


<<Iteration Tag>>

static int EVAL_BODY_AGAIN

int doAfterBody()


<<BodyTag>>

static int EVAL_BODY_BUFFERED
static int EVAL_BODY_TAG

void doInitBody()
void setBodyContent(BodyContent b)


TagSupport

protected String id
protected PageContext pageContext

TagSupport()

實作Tag的六個方法
實作Iteration Tag的一個方法(doAfterBody)
static Tag findAncestorWithClass(Tag from, Class klass)
String    getId()
Object    getValue(String k)
Enumeration getValues()
void    removeValue(String k)
void    setId(String id)
void    setValue(String k, Object o)


BodyTagSupport

protected  BodyContent bodyContent

BodyTagSupport()

實作Iteration Tag的一個方法(doAfterBody)
int    doEndTag()
void    doInitBody()
int    doStartTag()
BodyContent getBodyContent()
JspWriter   getPreviousOut()
void    release()
void    setBodyContent(BodyContent b)

2015年9月27日 星期日

空標籤 (客製化JSP Tag 一)

※無屬性Tag

EmptyTag.java
public class EmptyTag extends TagSupport {
    @Override
    public int doStartTag() throws JspException {
        try {
            pageContext.getOut().println("<h1>tag success</h1>");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // return TagSupport.SKIP_BODY
        return super.doStartTag();
    }
}

要繼承TagSupport並覆寫doStartTag()

 helloTag.tld
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" 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 http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
    <tlib-version>1.0</tlib-version>
    <short-name>ht</short-name>
    
    <tag>
        <name>helloTag</name>
        <tag-class>empty.EmptyTag</tag-class>
        <body-content>empty</body-content>
    </tag>
</taglib>

tld可以安裝jboss tools,它可以幫助產生taglib裡面的屬性,short-name必填

 empty.jsp
<%@taglib uri="WEB-INF/helloTag.tld" prefix="bruce" %>
<body>
    <bruce:helloTag />
</body>

※prefix寫什麼就用什麼開頭,「:」後面是tld有個tag,裡面的name
這樣就可以產生一個自訂的空標籤了

※因為是空標籤,所以<bruce:helloTag></bruce:helloTag>裡面不能放東西

※還可以配合web.xml使用,這樣uri就不用指定路徑了,只要指定web.xml的taglib-uri即可
web.xml
<jsp-config>
    <taglib>
        <taglib-uri>http://javabruce.blogspot.tw/empty</taglib-uri>
        <taglib-location>/WEB-INF/helloTag.tld</taglib-location>
    </taglib>
</jsp-config>

由web.xml連接tld,uri可以隨便打
而jsp的taglib,uri就要改成隨便打的字,如下:
<%@taglib uri="http://javabruce.blogspot.tw/empty" prefix="bruce" %>

※有屬性Tag

做一個數字格式化的範例
AttrTag.java
public class AttrTag extends TagSupport {
    private String format;
    private Double dou;
    public void setFormat(String format) {
        this.format = format;
    }
    public void setDou(Double dou) {
        this.dou = dou;
    }

    @Override
    public int doStartTag() throws JspException {
        NumberFormat formatter = new DecimalFormat(this.format);
        try {
            pageContext.getOut().write(formatter.format(dou));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.doStartTag();
    }
}

只要給setter就可以了

 attr.tld
<tag>
    <name>displayNumber</name>
    <tag-class>attr.AttrTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
        <name>format</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
        <name>dou</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>

attr.jsp
<%@taglib uri="http://javabruce.blogspot.tw/attr" prefix="bruce" %>
<bruce:displayNumber dou="12345.6789" format="#,###,###.###"/>

attribute的name會找到對應的setter

 web.xml
<jsp-config>
    <taglib>
        <taglib-uri>http://javabruce.blogspot.tw/empty</taglib-uri>
        <taglib-location>/WEB-INF/helloTag.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>http://javabruce.blogspot.tw/attr</taglib-uri>
        <taglib-location>/WEB-INF/attr.tld</taglib-location>
    </taglib>
</jsp-config>

這裡的web.xml連剛剛的無屬性Tag一起show出來
我用兩個jsp-config會變成404,所以看起來只能有一個jsp-config,然後對應多個taglib
可以參考這個網站

tld的required是true,表示用此標籤時,一定要加這個屬性
rtexprvalue是true時,支援表達式語言,如下:
<%
    pageContext.setAttribute("d", 54321.87654d);
    String f = "#,###,###.###";
%>
<bruce:displayNumber dou="${d}" format="<%=f%>"/>

${}就是表達式語言,<%=%>就不是,所以為false時,就會出500,According to TLD or attribute directive in tag file, attribute xxx does not accept any expressions