J2EE——第15章JSP页中的自定义标签

clangpotatoSoftware and s/w Development

Oct 28, 2013 (3 years and 10 months ago)

125 views

J2EE
——

15


JSP
页中的自定义标签

什么是自定义标签


可以:在隐式对象上操作、处理表单、访问数
据库和其它企业服务、实现流控制


可以用
JSP
语言或
Java
语言编写标签处理程序


还可以:


通过从调用页传递的属性进行定制


把变量传递回调用页


访问
JSP
页可用的所有对象


彼此通信:创建和初始化
bean
、在一个标签中创建
引用该
bean

EL
变量、在另一个标签中使用该
bean


彼此进行嵌套,并通过私有变量进行通信

示例
JSP


标签的类型

<tt:tag>body</tt:tag>

<tt:tag />


<tt:tag></tt:tag>


简单属性
<sc:catalog bookDB ="${bookDB}" color="#cccccc">


段属性

<sc:catalog bookDB ="${bookDB}" color="#cccccc">


<jsp:attribute name="normalPrice">


<fmt:formatNumber value="${price}" type="currency"/>


</jsp:attribute> <jsp:attribute name="onSale">


<fmt:formatNumber value="${price}


type="currency"/>


<fmt:formatNumber value="${salePrice}


type="currency"/>


</jsp:attribute></sc:catalog>


动态属性
<colored:colored color1="red" color2="yellow"
color3="blue"/>

jsp:attribute
元素和具有体的标签

<c:if test="${param.Clear}">


<font color="#ff0000" size="+2"><strong> You just cleared your
shopping cart! </strong><br>&nbsp;<br></font>

</c:if>

<tt:parameter name="title" direct="true">


<jsp:attribute name="value" >


<fmt:message key="TitleBookCatalog"/>


</jsp:attribute>


<jsp:body>


the tag body


</jsp:body>

</tt:parameter>

定义变量的标签和标签之间的通信

<tlt:iterator var="departmentName" type="java.lang.String"

group="${myorg.departmentNames}">

<tr><td><a href="list.jsp?deptName=${departmentName}">

${departmentName}</a></td></tr>

</tlt:iterator>


<c:set var="aVariable" value="aValue" />

<tt:anotherTag attr1="${aVariable}" />


<tt:outerTag>


<tt:innerTag />

</tt:outerTag>

用标签文件封装可重用内容


response.tag

<%@ attribute name="greeting" required="true" %>

<%@ attribute name="name" required="true" %>

<h2><font color="black">${greeting}, ${name}!</font></h2>


greeting.jsp

<%@ taglib tagdir="/WEB
-
INF/tags" prefix="h" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<c:set var="greeting" value="Hello" />

<form method="get"> <input type="text" name="username" size="25">

<input type="submit" value="Submit"></form>

<c:if test="${fn:length(param.username) > 0}" >

<h:response greeting="${greeting}


name="${param.username}"/>

</c:if>

标签文件位置和标签文件指令


/WEB
-
INF/tags
及其子目录
,./WEB
-
INF/lib

jar
文件


打包的标签文件要求标签库描述符
.tld
文件


标签文件指令


taglib


include


tag
(类似
JSP
中的
page



attribute


variable

tag
指令属性


display
-
name


body
-
content


dynamic
-
attributes


small
-
icon


large
-
icon


description


example


language


import


pageEncoding


isELIgnored

attribute
指令
(IN
参数
)
属性


description


name


required


rtexprvalue


type


fragment

variable
指令
(OUT
参数
)
属性


description


name
-
given

name
-
from
-
attribute


alias


variable
-
class


declare


scope

变量同步-
AT_BEGIN
作用域

<%
--

callingpage.jsp
--
%>

<c:set var="x" value="1"/>

${x} <%
--

(x == 1)
--
%>

<my:example>

${x} <%
--

(x == 2)
--
%>

</my:example>

${x} <%
--

(x == 4)
--
%>

<%
--

example.tag
--
%>

<%@ variable name
-
given="x" scope="AT_BEGIN" %>

${x} <%
--

(x == null)
--
%>

<c:set var="x" value="2"/>

<jsp:doBody/>

${x} <%
--

(x == 2)
--
%>

<c:set var="x" value="4"/>

变量同步-
NESTED
作用域

<%
--

callingpage.jsp
--
%>

<c:set var="x" value="1"/>

${x} <%
--

(x == 1)
--
%>

<my:example>

${x} <%
--

(x == 2)
--
%>

</my:example>

${x} <%
--

(x == 1)
--
%>

<%
--

example.tag
--
%>

<%@ variable name
-
given="x" scope="NESTED" %>

${x} <%
--

(x == null)
--
%>

<c:set var="x" value="2"/>

<jsp:doBody/>

${x} <%
--

(x == 2)
--
%>

<c:set var="x" value="4"/>

变量同步-
AT_END
作用域

<%
--

callingpage.jsp
--
%>

<c:set var="x" value="1"/>

${x} <%
--

(x == 1)
--
%>

<my:example>

${x} <%
--

(x == 1)
--
%>

</my:example>

${x} <%
--

(x == 4)
--
%>

<%
--

example.tag
--
%>

<%@ variable name
-
given="x" scope="AT_END" %>

${x} <%
--

(x == null)
--
%>

<c:set var="x" value="2"/>

<jsp:doBody/>

${x} <%
--

(x == 2)
--
%>

<c:set var="x" value="4"/>

变量同步-
AT_BEGIN

name
-
from
-
attribute

<%
--

callingpage.jsp
--
%>

<c:set var="x" value="1"/>${x} <%
--

(x == 1)
--
%>

<my:example var="x">

${x} <%
--

(x == 2)
--
%>${result} <%
--

(result == null)
--
%>

<c:set var="result" value="invisible"/></my:example>

${x} <%
--

(x == 4)
--
%>${result} <%
--

(result ==

invisible

)
--
%>

<%
--

example.tag
--
%>

<%@ attribute name="var" required="true" rtexprvalue="false"%>

<%@ variable alias="result" name
-
from
-
attribute="var


scope="AT_BEGIN" %>

${x} <%
--

(x == null)
--
%> ${result} <%
--

(result == null)
--
%>

<c:set var="x" value="ignored"/><c:set var="result" value="2"/>

<jsp:doBody/>${x} <%
--

(x ==

ignored

)
--
%>

${result} <%
--

(result == 2)
--
%>

<c:set var="result" value="4"/>

简单属性示例

<%@ taglib prefix="sc" tagdir="/WEB
-
INF/tags" %>

<sc:shipDate shipping="${param.shipping}" />


<%@ attribute name="shipping" required="true" %>

<jsp:useBean id="now" class="java.util.Date" />

<jsp:useBean id="shipDate" class="java.util.Date" />

<c:choose> <c:when test="${shipping == 'QuickShip'}">

<c:set var="days" value="2" /> </c:when>

<c:when test="${shipping == 'NormalShip'}">

<c:set var="days" value="5" /> </c:when> </c:choose>

<jsp:setProperty name="shipDate" property="time"

value="${now.time + 86400000 * days}" />

<fmt:formatDate value="${shipDate}" type="date" dateStyle="full"/>

简单和段属性及变量示例
catalog.tag

<%@ attribute name="bookDB" required="true" type="database.BookDB" %>

<%@ attribute name="color" required="true" %>

<%@ attribute name="normalPrice" fragment="true" %>

<%@ attribute name="onSale" fragment="true" %>

<%@ variable name
-
given="price" %>

<%@ variable name
-
given="salePrice" %>

<c:forEach var="book" begin="0" items="${bookDB.books}">

<c:set var="salePrice" value="${book.price * .85}" />

<c:set var="price" value="${book.price}" />

<c:choose>


<c:when test="${book.onSale}"><jsp:invoke fragment="onSale"/>
</c:when>


<c:otherwise><jsp:invoke fragment="normalPrice"/></c:otherwise>

</c:choose>

简单和段属性及变量示例
bookcatalog.jsp

<sc:catalog bookDB ="${bookDB}" color="#cccccc">


<jsp:attribute name="normalPrice">


<fmt:formatNumber value="${price}" type="currency"/>


</jsp:attribute>


<jsp:attribute name="onSale">


<strike>


<fmt:formatNumber value="${price}" type="currency"/>


</strike><br/>


<font color="red">


<fmt:formatNumber value="${salePrice}" type="currency"/>


</font>


</jsp:attribute>

</sc:catalog>

动态属性示例

<%@ tag dynamic
-
attributes="colorMap"%>

<ul>

<c:forEach var="color" begin="0


tems="${colorMap}">


<li>${color.key} =


<font color="${color.value}">${color.value}</font><li>

</c:forEach>

</ul>

标签库描述符

<taglib 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/webjsptaglibrary
_2_0.xsd" version="2.0">


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


<short
-
name>bar
-
baz</short
-
name>


<tag
-
file>


<name>d</name>


<path>/WEB
-
INF/tags/bar/baz/d.tag</path>


</tag
-
file>

</taglib>


标签库描述符文件
*
.tld

/WEB
-
INF
目录中


打包到
.jar
文件中,在
META
-
INF
目录


标签文件在
/WEB
-
INF/tags
目录,
Web
容器自动生成
.tld
文件


打包在
jar
中的标签文件在
/META
-
INF/tags
目录,需要定义
tld

声明标签处理程序

<tag>


<name>present</name>


<tag
-
class>condpkg.IfSimpleTag</tag
-
class>


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


...


<attribute>


<name>test</name>


<required>true</required>


<rtexprvalue>true</rtexprvalue>


</attribute>


...

</tag>

声明标签处理程序的标签变量

<tlt:iterator var="departmentName" type="java.lang.String"
group="${myorg.departmentNames}">

<tr> <td><a href="list.jsp?deptName=${departmentName}">
${departmentName}</a></td> </tr>

</tlt:iterator>


<tag>

<variable>


<name
-
given>var</name
-
given>


<variable
-
class>java.lang.String</variable
-
class>
<declare>true</declare>


<scope>NESTED</scope>

</variable>

</tag>
TagExtraInfo


编写简单标签处理程序


简单标签处理程序是如何调用的

ATag t = new ATag();

t.setJSPContext(...);

t.setParent(...);

t.setAttribute1(value1);

t.setAttribute2(value2);

...

t.setJspBody(new JspFragment(...))

t.doTag();


基本标签的标签处理程序

public HelloWorldSimpleTag extends SimpleTagSupport {

public void doTag() throws JspException, IOException{


getJspContext().getOut().write("Hello, world."); } }

具有属性的标签的标签处理程序

<c:if test="${Clear}">public void setTest(boolean test) {this.test = test;}

<attribute>


<name>attr1</name> <required>true</required>


<rtexprvalue>true</rtexprvalue>

</attribute>

public class TwaTEI extends TagExtraInfo {


public ValidationMessage[] validate(TagData data) {


Object o = data.getAttribute("attr1");


if (o != null && o != TagData.REQUEST_TIME_VALUE) {


if (((String)o).toLowerCase().equals("true") ||


((String)o).toLowerCase().equals("false") ) return null;


else return new ValidationMessage(


data.getId(), "Invalid boolean value.");


} else return null;}}

设置动态属性

private ArrayList keys = new ArrayList();

private ArrayList values = new ArrayList();

public void setDynamicAttribute(String uri, String localName, Object value )
throws JspException { keys.add( localName ); values.add( value ); }

public void doTag() throws JspException, IOException {


JspWriter out = getJspContext().getOut();


for( int i = 0; i < keys.size(); i++ ) {


String key = (String)keys.get( i );


Object value = values.get( i );


out.println( "<li>" + key + " = " + value + "</li>" );


}

}

具有体的标签的标签处理程序

public class IfSimpleTag extends SimpleTagSupport {

private boolean test;

public void setTest(boolean test) {this.test = test; }

public void doTag() throws JspException, IOException {


if(test){getJspBody().invoke(null);}}}


public class SimpleWriter extends SimpleTagSupport {


public void doTag() throws JspException, IOException {


StringWriter sw = new StringWriter();


getJspBody.invoke(sw);


getJspContext().getOut().println(sw.toString().toUpperCase());


}

}

定义变量的标签的标签处理程序

public void doTag() throws JspException, IOException {


if (iterator == null) return;


while (iterator.hasNext()) {


getJspContext().setAttribute(var, iterator.next());


getJspBody().invoke(null);


}

}

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

public void setGroup(Collection group) {


this.group = group;


if(group.size() > 0) iterator = group.iterator();

}

对象的作用域

TagExtraInfo



声明标签处理程序的标签变量

package iterator;

public class IteratorTEI extends TagExtraInfo {


public VariableInfo[] getVariableInfo(TagData data) {


String type = data.getAttributeString("type");


if (type == null) type = "java.lang.Object";


return new VariableInfo[] {


new VariableInfo(data.getAttributeString("var"), type, true,


VariableInfo.NESTED)


};}}


<tei
-
class>iterator.IteratorTEI</tei
-
class>

协作标签
(1)

public class QueryTag extends SimpleTagSupport {


public int doTag() throws JspException {


String cid = getConnectionId(); Connection connection;


if (cid != null) {


connection =(Connection)pageContext. getAttribute(cid);


} else { ConnectionTag ancestorTag =


(ConnectionTag)findAncestorWithClass(this, ConnectionTag.class);


if (ancestorTag == null) {


throw new JspTagException("A query without


a connection attribute must be nested within a connection tag.");


}


connection = ancestorTag.getConnection();

...}}}

协作标签
(2)

<tt:connection cid="con01" ... >... </tt:connection>

<tt:query id="balances" connectionId="con01">


SELECT account, balance FROM acct_table where customer_number = ?


<tt:param value="${requestScope.custNumber}" />

</tt:query>


<tt:connection ... >


<tt:query cid="balances">


SELECT account, balance FROM acct_table where customer_number = ?


<tt:param value="${requestScope.custNumber}" />


</tt:query>

</tt:connection>


<tag>...<attribute><name>connectionId</name>

<required>false</required>

</attribute></tag>

示例-迭代标签-
JSP


<%@ taglib uri="/tlt" prefix="tlt" %>

<jsp:useBean id="myorg" class="myorg.Organization"/>

<table border=2 cellspacing=3 cellpadding=3>

<tlt:iterator var="departmentName" type="java.lang.String"

group="${myorg.departmentNames}">


<tr>


<td><a href="list.jsp?deptName=${departmentName}">


${departmentName}</a></td>


</tr>

</tlt:iterator>

</table>

示例-迭代标签-标签处理程序

public void doTag() throws JspException, IOException {


if (iterator == null) return;


while (iterator.hasNext()) {


getJspContext().setAttribute(var, iterator.next());


getJspBody().invoke(null);


}

}

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

public void setGroup(Collection group) {


this.group = group;


if(group.size() > 0) iterator = group.iterator();

}

示例-模版标签库-
template.jsp

<%@ taglib uri="/tutorial
-
template" prefix="tt" %>

<%@ page errorPage="/template/errorinclude.jsp" %>

<%@ include file="/template/screendefinitions.jsp" %>

<html>

<head><title>

<tt:insert definition="bookstore" parameter="title"/>

</title></head>

<body bgcolor="#FFFFFF">

<tt:insert definition="bookstore" parameter="banner"/>

<tt:insert definition="bookstore" parameter="body"/>

</body>

</html>

示例-模版标签库
screendefinitions.jsp

<tt:definition name="bookstore"
screen="${requestScope['javax.servlet.forward.servlet_path']}">

<tt:screen id="/bookstore">


<tt:parameter name="title" value="Duke's Bookstore" direct="true"/>


<tt:parameter name="banner" value="/template/banner.jsp" direct="false"/>


<tt:parameter name="body" value="/bookstore.jsp" direct="false"/>

</tt:screen>

<tt:screen id="/bookcatalog">


<tt:parameter name="title" direct="true">


<jsp:attribute name="value" ><fmt:message key="TitleBookCatalog"/>


</jsp:attribute></tt:parameter>

<tt:parameter name="banner" value="/template/banner.jsp" direct="false"/>

<tt:parameter name="body" value="/bookcatalog.jsp


direct="false"/>

</tt:screen></tt:definition>

示例-模版标签库-
Dispatcher.java

public class Dispatcher extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse
response) {


String selectedScreen = request.getServletPath();


if (selectedScreen.equals("/bookcatalog")) {


bookId = request.getParameter("Add");


if (!bookId.equals("")) {


book = bookDBAO.getBookDetails(bookId);


cart.add(bookId, book);


}else if (

)


}


request.getRequestDispatcher("/template/template.jsp").


forward(request, response);

}

示例-模版标签库-
DefinitionTag.java

public int doTag() {


screens = new HashMap(); getJspBody().invoke(null);


Definition definition = new Definition();


PageContext context = (PageContext)getJspContext();


ArrayList params = (ArrayList) screens.get(screenId);


Iterator ir = null;


if (params != null) {


ir = params.iterator();


while (ir.hasNext()) {definition.setParam((Parameter)ir.next());}


context.setAttribute(definitionName, definition,


context.APPLICATION_SCOPE);

} }

示例-模版标签库-
InsertTag.java

public void doTag() throws JspTagException {


Definition definition = null; Parameter parameter = null;


boolean directInclude = false;


PageContext context = (PageContext)getJspContext();


definition = (Definition)context.getAttribute( definitionName,


context.APPLICATION_SCOPE);


if (parameterName != null && definition != null)


parameter = (Parameter) definition.getParam(parameterName);


if (parameter != null) directInclude = parameter.isDirect();


if (directInclude && parameter != null)


context.getOut().print(parameter.getValue());


else { if ((parameter != null) && (parameter.getValue() != null))


context.include(parameter.getValue());

} }