Java for Web學習筆記(三六):自訂tag(4)自訂Tag檔案__Java

來源:互聯網
上載者:User
Tag檔案中的Directives

Tag檔案和jsp很相似,也有不同,主要的不同在directives。Jsp的directive有include,taglib和page,但tag中有include和taglib,沒有page,此外還提供了tag,tag替代了jsp中的page,並提供了tld檔案中<tag>的配置功能。

tag directive有下面屬性,均為可選: pageEncoding:同page中的含義,定義tag輸出的編碼。 isELIgnored:同page中的含義,要求container不計算EL運算式,預設為false。 language:同page中的含義,目前只支援java。 deferredSyntaxAllowedAsLiteral:同page中的含義,要求container忽略和不對延遲EL文法進行解析。 trimDirectiveWhitespaces:同page中的含義,將directives周圍的空格trim掉。 import:同page中的含義,可以引入java類,多個通過逗號分隔。 descriptiondisplay-namesmall-iconlarge-icon:通tld中的定義,略 body-content:是tld種的body-content的替代,但略有差異,有效值為empty, scriptless和tagdependent,沒有jsp,即在tag檔案中不允許使用scriptlets和expressions。預設值為scriptless。 dynamic-attributes:同tld,表明是否允許動態屬性,預設為空白,即不支援動態屬性。如果需要設定,則設定為你需要獲得所有動態變數的EL名字,這個EL是Map<String, String>類型,key是動態變數的名字,value是動態變數的值。 example:同tld,但在directive中進行有效設定比較困難。

此外,derective還有variable和attribute,同tld中的variable和attribute。variable有description, name-given, name-from-attribute,variable-class, declare, scope屬性,同tld,此外還有alias,可以定義在一個本地變數名字來使用tag檔案內的變數。attribute屬性有 description, name, required, rtexprvalue, type, fragment, deferredValue,deferredValueType, deferredMethod和deferredMethodSignature,同tld。 一個簡單的HTML模板Tag

我們寫一個簡單的tag檔案,作為HTML的模板,方便填入HTML的title,編碼等常規內容。建立/WEB-INF/tags/template/main.tag檔案,如下:

<!-- body-content="scriptless":因為要支援HTML body內容,不使用empty,也不選擇tagdependent(在通過query tag傳遞SQL statement時使用tagdependent)。--><!-- dynamic-attributes:支援動態屬性(即EL),擷取的參數名字為dynamicAttributes --><!-- 空格trim。在web.xml的<jsp-config>中我們定義了<trim-directive-whitespaces>true</trim-directive-whitespaces>,但是這個對tag檔案無影響,因此我們需要在每個tag檔案中手工進行定義 --><%@ tag body-content="scriptless" dynamic-attributes="dynamicAttributes" trimDirectiveWhitespaces="true" %><!-- 屬性名稱字為htmlTitle;類型(String);該值允許runtime expression(rtexpvalue=true),即允許EL或者指令碼運算式;必選(required=true) --><%@ attribute name="htmlTitle" type="java.lang.String" rtexprvalue="true" required="true" %><!-- 因為web.xml中jsp-conf設定不影響tag檔案,如果我們在base.jspf中定義了共同的引入,需要再次手動引入,當然我們也可以通過%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %之類進行引入。 --><%@ include file="/WEB-INF/jsp/base.jspf" %><!DOCTYPE html><!-- 這裡示範了動態屬性加到現有html標籤的例子:當中的c:out提供兩個功能:顯示value之前加了空格,即確保每個屬性之前存在空格;禁止escapeXML,由於這些html的屬性要真實有效,因此參數名不能escapeXML --><html<c:forEach items="${dynamicAttributes}" var="a">         <c:out value=' ${a.key}="${fn:escapeXml(a.value)}"' escapeXml="false" />     </c:forEach>>     <head>     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">     <!-- 設定title,刪除前後的空格trim -->        <title><c:out value="${fn:trim(htmlTitle)}" /></title>    </head>    <!-- jsp:doBody 僅在tag檔案中使用,告訴容器計算JSP中本tag的body內容,並顯示出來。可以加上var varReader屬性和scope屬性,將輸入放入變數而不是顯示出來 -->    <body>        <jsp:doBody />    </body></html>

我們先補充一下base.jspf:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %><%@ taglib prefix="template" tagdir="/WEB-INF/tags/template" %>

相應的在web.xml中:

  <jsp-config>    <jsp-property-group>      <url-pattern>*.jsp</url-pattern>      <url-pattern>*.jspf</url-pattern>      <page-encoding>UTF-8</page-encoding>      <scripting-invalid>true</scripting-invalid>      <include-prelude>/WEB-INF/jsp/base.jspf</include-prelude>      <trim-directive-whitespaces>true</trim-directive-whitespaces>      <default-content-type>text/html</default-content-type>    </jsp-property-group>  </jsp-config>

下面是一個是用該tag的jsp例子hello.jsp。例子中Hello, Template!就是<jsp:body/>的內容。

<template:main htmlTitle="Template Homepage">    Hello, Template!</template:main>
小例子:HTML模板 更為複雜的的tag檔案:main.tag

我們將實現一個簡單實用的HTML模板,最上是標題,左邊是導覽列,右邊是具體內容,如下圖。


這裡我們定義了兩個fragment,分別對應HTML Title和導覽列。在官方文檔http://docs.oracle.com/javaee/5/tutorial/doc/bnama.html#bnamr中fragment 如下定義。簡單地說,fragment是可以包括html,jsp的一組指令碼。

(optional) Whether this attribute is a fragment to be evaluated by the tag handler (true) or a normal attribute to be evaluated by the container before being passed to the tag handler.If this attribute is true:You do not specify the rtexprvalue attribute. The container fixes the rtexprvalue attribute at true.You do not specify the type attribute. The container fixes the type attribute at javax.servlet.jsp.tagext.JspFragment.Defaults to false.

將fragment的內容顯示出來:

<jsp:invoke fragment="navigationContent" />

我們重寫main.tag檔案

<%@ tag body-content="scriptless" trimDirectiveWhitespaces="true" %><!-- 定義兩個String參數:分別是HTML title和body Title --><%@ attribute name="htmlTitle" type="java.lang.String" rtexprvalue="true" required="true" %><%@ attribute name="bodyTitle" type="java.lang.String" rtexprvalue="true" required="true" %><!-- 定義兩個fragment參數:分布是headConent(定義header的屬性)和navigationContent(定義導覽列內容) --><%@ attribute name="headContent" fragment="true" required="false" %><%@ attribute name="navigationContent" fragment="true" required="true" %><%@ include file="/WEB-INF/jsp/base.jspf" %><!DOCTYPE html><html><!-- header中,設定title以及header的其他屬性headContent --><head><title>Customer Support :: <c:out value="${fn:trim(htmlTitle)}" /></title><link rel="stylesheet" href="<c:url value="/resource/stylesheet/main.css" />" /><jsp:invoke fragment="headContent" /></head><body><h1>Multinational Widget Corporation</h1><table border="0" id="bodyTable"><tbody><tr><td class="sidebarCell"><!-- 對應為導覽列,因此invoke響應的fragment --><jsp:invoke fragment="navigationContent" /></td><td class="contentCell"><!-- 對應為內容 --><!-- 內容1:內容標題 --><h2><c:out value="${fn:trim(bodyTitle)}" /></h2><!-- 內容2:具體內容,將相應jsp body顯示即可 --><jsp:doBody/></td></tr></tbody></table></body></html>
如何設定fragment:loggedOut.tag

對於登入介面,沒有導覽列,實際上navigationCibtebt無實質內容,我們在main.tag的基礎上提供loggedOut.tag。main有四個參數必選參數,在loggedOut.tag中,我們固化當中的兩個fragment參數,另兩個String參數則作為新tag的參數。我們將重點學習通過<jsp:attribute>對fragment進行設定。

<%@ tag body-content="scriptless" trimDirectiveWhitespaces="true" %><!-- 定義兩個String參數,並作為傳遞到maintag中 --><%@ attribute name="htmlTitle" type="java.lang.String" rtexprvalue="true" required="true" %><%@ attribute name="bodyTitle" type="java.lang.String" rtexprvalue="true" required="true" %><%@ include file="/WEB-INF/jsp/base.jspf" %><template:main htmlTitle="${htmlTitle}" bodyTitle="${bodyTitle}"><!-- 設定headCotent參數。fragment都比較長,可能含有jsp代碼,這時需要通過jsp:attribute來進行設定。 --><jsp:attribute name="headContent"><link rel="stylesheet" href="<c:url value="/resource/stylesheet/login.css" />" /></jsp:attribute><!-- 設定navigationContent參數,由於沒有實際的邊框欄,因此該參數無實際值 --><jsp:attribute name="navigationContent" /><!-- tag的body作為具體內容,需要傳遞到main tag中的body。 --><jsp:body><jsp:doBody /></jsp:body></template:main>
具體化導覽列:basic.tag

main.tag是通用的模板,我們可以具體化到實際的項目中,包括: 將headContent映射為extraHeadContent。 將navigationContent具體化為通用的導航連結加上extraNavigationContent。

在這個例子中,我們將展現如果在fragment中使用其他fragment。

<%@ tag body-content="scriptless" trimDirectiveWhitespaces="true" %><!-- 仍使用四個參數 --><%@ attribute name="htmlTitle" type="java.lang.String" rtexprvalue="true" required="true" %><%@ attribute name="bodyTitle" type="java.lang.String" rtexprvalue="true" required="true" %><%@ attribute name="extraHeadContent" fragment="true" required="false" %><%@ attribute name="extraNavigationContent" fragment="true" required="false" %><%@ include file="/WEB-INF/jsp/base.jspf" %><template:main htmlTitle="${htmlTitle}" bodyTitle="${bodyTitle}"><!-- 將headContent映射為extraHeadContent --><jsp:attribute name="headContent"><jsp:invoke fragment="extraHeadContent" /></jsp:attribute><!-- 將navigationContent具體化為通用的導航連結加上extraNavigationContent。--><jsp:attribute name="navigationContent"><a href="<c:url value="/tickets" />">List Tickets</a><br /><a href="<c:url value="/tickets">  <c:param name="action" value="create" /> </c:url>">Create a Ticket</a><br /><a href="<c:url value="/sessions" />">List Sessions</a><br /><a href="<c:url value="/login?logout" />">Log Out</a><br /><jsp:invoke fragment="extraNavigationContent" /> </jsp:attribute><jsp:body><jsp:doBody /></jsp:body></template:main>
使用tag

使用者未登入或者登入失敗,重新導向至login.jsp,如果登入失敗,給出失敗提示。

<%--@elvariable id="loginFailed" type="java.lang.Boolean"--%><%@ taglib prefix="template" tagdir="/WEB-INF/tags/template" %><template:loggedOut htmlTitle="Log In" bodyTitle="Log In">You must log in to access the customer support site.<br /><br /><c:if test="${loginFailed}"><b>The username or password you entered are not correct. Please try again.</b></c:if><form method="POST" action="<c:url value="/login" />">Username<br/><input type="text" name="username" /><br/><br/>Password<br/><input type="password" name="password" /><br/><br/><input type="submit" value="Log in" /></form></body></template:loggedOut>

在LoginServlet.jsp中:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {... 判斷是否使用者登入成功  ...if(登入失敗){request.setAttribute("loginFailed", true);request.getRequestDispatcher("/WEB-INF/jsp/view/login.jsp").forward(request, response);}else{ //登入成功session.setAttribute("username", username);request.changeSessionId(); //這裡注意一下,基於安全,修改了sessionId。response.sendRedirect(......);}}

我們再看一個基於basic tag的例子,ticketForm.jsp

<template:basic htmlTitle="Create a Ticket" bodyTitle="Create a Ticket">        <form method="POST" action="tickets" enctype="multipart/form-data">            <input type="hidden" name="action" value="create"/>            Subject<br/>            <input type="text" name="subject"><br/><br/>            Body<br/>            <textarea name="body" rows="5" cols="30"></textarea><br/><br/>            <b>Attachments</b><br/>            <input type="file" name="file1"/><br/><br/>            <input type="submit" value="Submit"/>        </form></template:basic>

相關連結: 我的Professional Java for Web Applications相關文章

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.