自定義JSP標簽庫及Properties使用
自定義JSP標簽
自定義JSP標簽技術是在JSP 1.1版本中才出現的,它支持用戶在JSP文件中自定義標簽,這樣可以使JSP代碼更加簡潔。
這些可重用的標簽能處理復雜的邏輯運算和事務,或者定義JSP網頁的輸出內容和格式。
創建自定義JSP標簽的步驟
1.創建標簽的處理類。
2.創建標簽庫描述文件。
3.在JSP文件中引入標簽庫,然后插入標簽,例如:<mm:hello/>
JSP Tag API
Servlet容器在編譯JSP網頁時,如果遇到自定義標簽,就會調用這個標簽的處理類。
標簽處理類必須擴展以下兩個類之一:
javax.servlet.jsp.tagext.TagSupport
javax.servlet.jsp.tagext.BodyTagSupport
前者是后者的父類。
TagSupport類的主要方法
doStartTag()
Servlet容器遇到自定義標簽的起始標志時調用該方法。
doStartTag()方法返回一個整數值,用來決定程序的后續流程。它有兩個可選值:
Tag.SKIP_BODY:表示標簽之間的內容被忽略。
Tag.EVAL_BODY_INCLUDE:表示標簽之間的內容被正常執行。
doEndTag()
Servlet容器遇到自定義標簽的結束標志時調用該方法。
doEndTag()方法也返回一個整數值,用來決定程序后續流程。它有兩個可選值:
Tag.SKIP_PAGE:表示立刻停止執行JSP網頁,網頁上未處理的靜態內容和JSP程序均被忽略,任何已有的輸出內容立刻返回到客戶的瀏覽器上。
Tag.EVAL_PAGE:表示按照正常的流程繼續執行JSP網頁。
setValue(String k, Object o)
在標簽處理類中設置key/value。
getValue(String k)
在標簽處理類中根據參數key返回匹配的value。
removeValue(String k)
在標簽處理類中刪除key/value。
setPageContext(PageContext pc)
設置PageContext對象,該方法由Servlet容器在調用doStartTag()或doEndTag()方法前調用。
setParent(Tag t)
設置嵌套了當前標簽的上層標簽的處理類,該方法由Servlet容器在調用doStartTag()或doEndTag()方法前調用。
getParent()
返回嵌套了當前標簽的上層標簽的處理類。
TagSupport類的兩個重要屬性
parent:代表嵌套了當前標簽的上層標簽的處理類。
pageContext:代表Web應用中的javax.servlet.jsp.PageContext對象。
JSP容器在調用doStartTag()或doEndTag()方法前,會先調用setPageContext()和setParent()方法,設置pageContext和parent。
在doStartTag()或doEndTag()方法中可以通過getParent()方法獲取上層標簽的處理類;
在TagSupport類中定義了protected類型的pageContext成員變量,因此在標簽處理類中可以直接訪問pageContext變量。
PageContext類
PageContext類提供了保存和訪問Web應用的共享數據的方法:
setAttribute(String name, Object value, int scope)
getAttribute(String name, int scope)
其中,scope參數用來指定屬性存在的范圍,它的可選值包括:
PageContext.PAGE_SCOPE
PageContext.REQUEST_SCOPE
PageContext.SESSION_SCOPE
PageContext.APPLICATION_SCOPE
用戶自定義標簽屬性
在標簽中可以包含自定義的屬性,例如:
<prefix:mytag username=“zhangsan"> …… …… </prefix:mytag>
在標簽處理類中應該將這個屬性作為成員變量,並且分別提供設置和讀取屬性的方法,假定以上username為String類型,可以定義如下方法:
private String username; public void setUsername(String value){ this.username=value; } public String getUsername(){ return username; }
范例1 創建標簽
1.創建標簽的處理類:
package com.mengdd.tag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; public class MyTag extends TagSupport { @Override public int doStartTag() throws JspException { // pageContext 是TagSupport的protected的成員變量 JspWriter writer = this.pageContext.getOut();// 返回一個JspWriter try { writer.println("Hello World"); } catch (IOException e) { e.printStackTrace(); } return EVAL_BODY_INCLUDE; } @Override public int doEndTag() throws JspException { JspWriter writer = this.pageContext.getOut(); try { writer.println("Welcome"); } catch (IOException e) { e.printStackTrace(); } return EVAL_PAGE; } }
2.創建標簽庫描述文件
標簽庫描述文件的后綴名:.tld (tag lib descriptor)
它是一個標准的XML文件。
存放位置:必須跟web.xml在同一個目錄下,即WEB-INF下面。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.1</jsp-version> <short-name>myTag</short-name> <uri>/myTag</uri> <tag> <name>firstTag</name> <tag-class>com.mengdd.tag.MyTag</tag-class> <body-content>empty</body-content> </tag> </taglib>
3.在JSP文件中引入標簽庫,然后插入標簽,例如:<mm:hello/>
首先,新建一個JSP頁面,在第一行下面加上這么一行:
<%@ taglib uri="/myTag" prefix="hello" %>
其中uri和prefix是必填屬性,uri在.tld文件中定義,這里用來指定使用哪個標簽庫,prefix是前綴,表示用這個詞來指代該標簽庫,這里先隨便起一個名字。
在JSP頁面的body里面插入這個標簽:
<body> <p> <font color="blue"><hello:firstTag /> </font> </p> </body>
用瀏覽器訪問,頁面顯示:
Hello World Welcome
這是因為標簽處理類里輸出了該內容。
范例2:創建message標簽
創建一個能夠替換應用中JSP網頁的靜態文本的標簽,這個標簽名為message,它放在標簽庫中。
1.初始化操作
盡管裝載靜態文本的任務可以直接由標簽處理類來完成,但是把初始化的操作安排在Web應用啟動時完成更符合Web編程的規范。
首先,在WEB-INF下新建一個message.properties文件,其中存放的是鍵值對:
title=hello
body=world
然后創建一個InitServlet,刪除其在web.xml中的<servlet-mapping>配置,加上啟動設置:
<servlet> <servlet-name>InitServlet</servlet-name> <servlet-class>com.mengdd.tag.InitServlet</servlet-class> <load-on-startup>10</load-on-startup> </servlet>
InitServlet內容如下:
package com.mengdd.tag; import java.io.InputStream; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; public class InitServlet extends HttpServlet { @Override public void init() throws ServletException { Properties properties = new Properties(); try { ServletContext servletContext = getServletContext(); InputStream is = servletContext .getResourceAsStream("/WEB-INF/message.properties"); properties.load(is); is.close(); // 將properties對象放到application范圍內供其他組件使用 servletContext.setAttribute("properties", properties); } catch (Exception e) { } } }
2.標簽庫描述文件
標簽庫的描述文件如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.1</jsp-version> <short-name>myTag</short-name> <uri>/myTag</uri> <tag> <name>firstTag</name> <tag-class>com.mengdd.tag.MyTag</tag-class> <body-content>empty</body-content> </tag> <tag> <name>message</name> <tag-class>com.mengdd.tag.MyTag2</tag-class> <body-content>empty</body-content> <attribute> <name>key</name> <required>true</required> </attribute> </tag> </taglib>
3.標簽處理類:
package com.mengdd.tag; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.TagSupport; public class MyTag2 extends TagSupport { // 屬性,需要在標簽處理類中提供成員變量和get set方法 private String key; public String getKey() { return key; } public void setKey(String key) { this.key = key; } @Override public int doEndTag() throws JspException { try { // 首先,讀取properties Properties properties = (Properties) this.pageContext.getAttribute( "properties", PageContext.APPLICATION_SCOPE); // 獲取key對應的value String message = properties.getProperty(key); // 將message打印在頁面上 this.pageContext.getOut().println(message); } catch (Exception e) { } return EVAL_PAGE; } }
4.在頁面中使用:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/myTag" prefix="hello"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'tag1.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <p> <font color="blue"><hello:firstTag /> </font> </p> <p> <hello:message key="title"/><br/> <hello:message key="body"/><br/> </p> </body> </html>
頁面中會添加兩行,顯示鍵值title和body對應的value值,即hello和world。
用途:用來實現國際化時,可以定義多個.properties文件,對不同的語言,使用不同的文件。
參考資料
聖思園張龍老師Java Web系列視頻教程。