380 likes | 580 Views
J2EE —— 第 15 章 JSP 页中的自定义标签. 什么是自定义标签. 可以:在隐式对象上操作、处理表单、访问数据库和其它企业服务、实现流控制 可以用 JSP 语言或 Java 语言编写标签处理程序 还可以: 通过从调用页传递的属性进行定制 把变量传递回调用页 访问 JSP 页可用的所有对象 彼此通信:创建和初始化 bean 、在一个标签中创建引用该 bean 的 EL 变量、在另一个标签中使用该 bean 彼此进行嵌套,并通过私有变量进行通信. 示例 JSP 页. 标签的类型.
E N D
什么是自定义标签 • 可以:在隐式对象上操作、处理表单、访问数据库和其它企业服务、实现流控制 • 可以用JSP语言或Java语言编写标签处理程序 • 还可以: • 通过从调用页传递的属性进行定制 • 把变量传递回调用页 • 访问JSP页可用的所有对象 • 彼此通信:创建和初始化bean、在一个标签中创建引用该bean的EL变量、在另一个标签中使用该bean • 彼此进行嵌套,并通过私有变量进行通信
标签的类型 <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> <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()); } }