一、自定義標簽開發庫簡介
Tag接口的方法:
二、自定義標簽入門:輸出客戶機ip
1.編寫一個實現tag接口的java類
-
ViewIPTag.java
1 package com.web.tag; 2
3 import java.io.IOException; 4
5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.jsp.JspException; 7 import javax.servlet.jsp.JspWriter; 8 import javax.servlet.jsp.tagext.TagSupport; 9
10 //Tag接口實現類
11 public class ViewIPTag extends TagSupport{ 12 @Override 13 public int doStartTag() throws JspException { 14
15 HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest(); 16 JspWriter out = this.pageContext.getOut(); 17
18
19 String ip = request.getRemoteAddr(); 20 try { 21 out.print(ip); 22 } catch (IOException e) { 23 throw new RuntimeException(e); 24 } 25
26 return super.doStartTag(); 27 } 28 }
2.在tld文件中對標簽處理器類進行描述(tld文件的位置:WEB-INF下,可以抄apache-tomcat/webapps\examples\WEB-INF\jsp2\jsp2-example-taglib.tld)com.tld:這個文件放在WEB-INF目錄下
-
tld文件:
1 <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
4 version="2.0">
5
6 <description>A tag library exercising SimpleTag handlers.</description>
7 <tlib-version>1.0</tlib-version>
8 <short-name>com</short-name>
9 <uri>http://www.sina.cn</uri><!-- 綁定url -->
10
11
12 <tag>
13 <name>viewIP</name><!-- 標簽的名稱 -->
14 <tag-class>com.web.tag.ViewIPTag</tag-class><!-- 標簽實現類的完整類名 -->
15 <body-content>empty</body-content><!-- 標簽體為空 -->
16 </tag>
17
18 </taglib>
3.在jsp頁面中導入和使用自定義標簽
-
1.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="http://www.sina.cn" prefix="com" %> <!-- 導入標簽 -->
3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
7 <title>Insert title here</title>
8 </head>
9 <body>
10 您的ip:<com:viewIP/><!-- 使用標簽 -->
11 </body>
12 </html>
三、Tag接口的執行流程
自定義標簽調用圖:
jsp翻譯成servlet部分源代碼:
1 out.write(" 您的ip是:"); 2 if (_jspx_meth_com_005fviewIP_005f0(_jspx_page_context)) 3 return; 4 out.write("\r\n"); 5 out.write(" </body>\r\n"); 6 out.write("</html>\r\n"); 7 } catch (java.lang.Throwable t) { 8 if (!(t instanceof javax.servlet.jsp.SkipPageException)){ 9 out = _jspx_out; 10 if (out != null && out.getBufferSize() != 0) 11 try { 12 if (response.isCommitted()) { 13 out.flush(); 14 } else { 15 out.clearBuffer(); 16 } 17 } catch (java.io.IOException e) {} 18 if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); 19 else throw new ServletException(t); 20 } 21 } finally { 22 _jspxFactory.releasePageContext(_jspx_page_context); 23 } 24 } 25
26 private boolean _jspx_meth_com_005fviewIP_005f0(javax.servlet.jsp.PageContext _jspx_page_context) 27 throws java.lang.Throwable { 28 javax.servlet.jsp.PageContext pageContext = _jspx_page_context; 29 javax.servlet.jsp.JspWriter out = _jspx_page_context.getOut(); 30 // com:viewIP
31 com.web.tag.ViewIPTag _jspx_th_com_005fviewIP_005f0 = (com.web.tag.ViewIPTag) _005fjspx_005ftagPool_005fcom_005fviewIP_005fnobody.get(com.web.tag.ViewIPTag.class); 32 boolean _jspx_th_com_005fviewIP_005f0_reused = false; 33 try { 34 _jspx_th_com_005fviewIP_005f0.setPageContext(_jspx_page_context);//調用setPageContext()方法
35 _jspx_th_com_005fviewIP_005f0.setParent(null); 36 int _jspx_eval_com_005fviewIP_005f0 = _jspx_th_com_005fviewIP_005f0.doStartTag(); 37 if (_jspx_th_com_005fviewIP_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) { 38 return true; 39 } 40 _005fjspx_005ftagPool_005fcom_005fviewIP_005fnobody.reuse(_jspx_th_com_005fviewIP_005f0); 41 _jspx_th_com_005fviewIP_005f0_reused = true; 42 } finally { 43 org.apache.jasper.runtime.JspRuntimeLibrary.releaseTag(_jspx_th_com_005fviewIP_005f0, _jsp_getInstanceManager(), _jspx_th_com_005fviewIP_005f0_reused); 44 } 45 return false; 46 }
四、 傳統標簽開發技術
開發人員在編寫Jsp頁面時,經常還需要在頁面中引入一些邏輯:
1、控制jsp頁面某一部分內容是否執行
API:
-
標簽實現類:TagDemo1.java
1 package com.web.tag; 2
3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.tagext.TagSupport; 5
6 public class TagDemo1 extends TagSupport{ 7
8 @Override 9 public int doStartTag() throws JspException { 10
11 //實際開發場景————如果有權限則輸出,沒有權限則不輸出
12 return TagSupport.EVAL_BODY_INCLUDE; 13 } 14
15 }
-
標簽聲明:tld文件
1 <tag>
2 <name>demo1</name>
3 <tag-class>com.web.tag.TagDemo1</tag-class>
4 <body-content>JSP</body-content><!--標簽體的內容 empty JSP scriptless tagdepentend-->
5 </tag>
6
tld文件類型中的四種標簽體:EMPTY JSP scriptless tagdepentend
-
使用標簽:jsp頁面
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="http://www.sina.cn" prefix="com" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>使用自定義標簽控制jsp部分內容是否輸出(標簽體)</title>
7 </head>
8 <com:demo1>hahaha</com:demo1>
9 <body>
10
11 </body>
12 </html>
2、控制整個jsp頁面內容是否執行
API:
-
標簽實現類:TagDemo2.java:
-
標簽聲明:tld文件
1 <tag>
2 <name>demo2</name>
3 <tag-class>com.web.tag.TagDemo2</tag-class>
4 <body-content>empty</body-content><!--標簽體為空-->
5 </tag>
6
-
使用標簽:
3、控制標簽體重復輸出
API:
-
標簽實現類:TagDemo3
1 package com.web.tag; 2
3 import javax.servlet.jsp.JspException; 4 import javax.servlet.jsp.tagext.IterationTag; 5 import javax.servlet.jsp.tagext.Tag; 6 import javax.servlet.jsp.tagext.TagSupport; 7 //控制標簽體輸出5次
8 public class TagDemo3 extends TagSupport{ 9 //次數
10 int x = 5; 11 @Override 12 public int doStartTag() throws JspException { 13 return Tag.EVAL_BODY_INCLUDE; 14 } 15
16 @Override 17 //在標簽體執行完之后、結束標簽之前調用
18 public int doAfterBody() throws JspException { 19 x--; 20 if(x>0){ 21 return IterationTag.EVAL_BODY_AGAIN; 22 }else { 23 return IterationTag.SKIP_PAGE; 24 } 25 } 26 }
-
標簽聲明:
1 <tag>
2 <name>demo3</name>
3 <tag-class>com.web.tag.TagDemo3</tag-class>
4 <body-content>JSP</body-content>
5 </tag>
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="http://www.sina.cn" prefix="com" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>使用自定義標簽控制jsp部分內容是否輸出(標簽體)</title>
7 </head>
8 <body>
9 <com:demo3>控制標簽體重復輸出 <br/></com:demo3>
10 </body>
11 </html>
4、改變標簽體內容輸出
API:
-
標簽實現類:TagDemo4.java:
1 package com.web.tag; 2
3 import java.io.IOException; 4
5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.tagext.BodyContent; 7 import javax.servlet.jsp.tagext.BodyTag; 8 import javax.servlet.jsp.tagext.BodyTagSupport; 9 import javax.servlet.jsp.tagext.Tag; 10
11 //修改標簽體內容輸出
12 public class TagDemo4 extends BodyTagSupport{ 13
14 @Override 15 public int doStartTag() throws JspException { 16 return BodyTag.EVAL_BODY_BUFFERED;//返回這個參數,服務器會把標簽體封裝成對象作為參數調用setBodyContent(BodyContent b)方法
17 } 18 @Override 19 public int doEndTag() throws JspException { 20 //得到標簽體
21 BodyContent bc = this.getBodyContent(); 22 //得到內容
23 String content = bc.getString(); 24 //轉成大寫
25 content = content.toUpperCase(); 26
27 try { 28 this.pageContext.getOut().write(content); 29 } catch (IOException e) { 30 throw new RuntimeException(e); 31 } 32
33 return Tag.EVAL_PAGE;//繼續輸出jsp頁面其他內容
34 } 35 }
當在doStartTag()方法中返回BodyTag.EVAL_BODY_BUFFERED參數時,服務器會把標簽體內容封裝成對象作為參數調用setBodyContent(BodyContent b)方法,然后在doEngTag()
中調用getBodyContent()方法返回BodyContent對象,從而得到標簽體內容進行修改輸出。
-
標簽聲明:
1 <tag>
2 <name>demo4</name>
3 <tag-class>com.web.tag.TagDemo4</tag-class>
4 <body-content>JSP</body-content>
5 </tag>
6
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="http://www.sina.cn" prefix="com" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>使用自定義標簽控制jsp部分內容是否輸出(標簽體)</title>
7 </head>
8 <com:demo4>aaaaaa</com:demo4>
9 <body>
10
11 </body>
12 </html>
5、Tag接口的體系:
五、簡單標簽開發技術
由於傳統標簽使用三個標簽接口來完成不同的功能,顯得過於繁瑣,不利於標簽技術的推廣, SUN公司為降低標簽技術的學習難度,在JSP 2.0中定義了一個更為簡單、便於編寫和調用的SimpleTag接口來實現標簽的功能。實現SimpleTag接口的標簽通常稱為簡單標簽。簡單標簽共定義了5個方法:
- setJspContext方法
- setParent和getParent方法
- setJspBody方法
- doTag方法
API:
實現類:
1、控制標簽體是否執行
-
標簽實現類:SimpleTagDemo1.java:
1 import javax.servlet.jsp.JspException; 2 import javax.servlet.jsp.tagext.JspFragment; 3 import javax.servlet.jsp.tagext.SimpleTagSupport; 4 //控制標簽體是否執行
5 public class SimpleTagDemo1 extends SimpleTagSupport{ 6
7 @Override 8 public void doTag() throws JspException, IOException { 9 //獲取標簽體對象
10 JspFragment jf = this.getJspBody(); 11 12
13 jf.invoke(this.getJspContext().getOut());//null也可以默認輸出給瀏覽器
14 15
16 } 17 }
-
標簽聲明:
1 <?xml version="1.0" encoding="UTF-8" ?>
2
3 <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
6 version="2.0">
7
8 <description>A tag library exercising SimpleTag handlers.</description>
9 <tlib-version>1.0</tlib-version>
10 <short-name>simple</short-name>
11 <uri>/simpletag</uri>
12
13
14 <tag>
15 <name>demo1</name>
16 <tag-class>com.web.simpletag.SimpleTagDemo1</tag-class>
17 <body-content>scriptless</body-content><!-- jsp2.0之后不運行標簽體里面寫腳本代碼,所以用scriptless -->
18 </tag>
19
20 </taglib>
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/simpletag" prefix="simple" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>My JSP '1.jsp' starting page</title>
7 </head>
8
9 <body>
10 <simple:demo1>hahaha <br/></simple:demo1>
11 </body>
12 </html>
2、控制標簽體重復執行
-
標簽實現類:
1 package com.web.simpletag; 2
3 import java.io.IOException; 4
5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.tagext.JspFragment; 7 import javax.servlet.jsp.tagext.SimpleTagSupport; 8 //控制標簽體重復執行
9 public class SimpleTagDemo2 extends SimpleTagSupport{ 10
11 @Override 12 public void doTag() throws JspException, IOException { 13 JspFragment jf = this.getJspBody(); 14 for(int i=0;i<5;i++){ 15 jf.invoke(this.getJspContext().getOut()); 16 } 17 } 18
19 }
-
標簽聲明:
1 <tag>
2 <name>demo2</name>
3 <tag-class>com.web.simpletag.SimpleTagDemo2</tag-class>
4 <body-content>scriptless</body-content><!-- jsp2.0之后不運行標簽體里面寫腳本代碼,所以用scriptless -->
5 </tag>
6
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/simpletag" prefix="simple" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>My JSP '1.jsp' starting page</title>
7 </head>
8
9 <body>
10 <simple:demo2>控制標簽體重復執行<br/></simple:demo2>
11 </body>
12 </html>
3、修改標簽體內容
-
標簽實現類:
1 package com.web.simpletag; 2
3 import java.io.IOException; 4 import java.io.StringWriter; 5
6 import javax.servlet.jsp.JspException; 7 import javax.servlet.jsp.tagext.JspFragment; 8 import javax.servlet.jsp.tagext.SimpleTagSupport; 9 //修改標簽體
10 public class SimpleTagDemo3 extends SimpleTagSupport{ 11
12 @Override 13 public void doTag() throws JspException, IOException { 14 JspFragment jf = this.getJspBody(); 15
16 //帶緩沖的流
17 StringWriter sw = new StringWriter(); 18 //把標簽體內容寫入緩沖流中
19 jf.invoke(sw); 20
21 //得到標簽體內容
22 String content = sw.getBuffer().toString(); 23
24 //修改標簽體
25 content = content.toUpperCase(); 26
27 //輸出
28 this.getJspContext().getOut().write(content); 29
30 } 31 }
-
標簽聲明:
1 <tag>
2 <name>demo3</name>
3 <tag-class>com.web.simpletag.SimpleTagDemo3</tag-class>
4 <body-content>scriptless</body-content><!-- jsp2.0之后不運行標簽體里面寫腳本代碼,所以用scriptless -->
5 </tag>
6
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/simpletag" prefix="simple" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>My JSP '1.jsp' starting page</title>
7 </head>
8
9 <body>
10 <simple:demo3>aaaaaaaa<br/></simple:demo3>
11 </body>
12 </html>
4、控制整個jsp頁面是否輸出
-
標簽實現類:
1 package com.web.simpletag; 2
3 import java.io.IOException; 4 import java.io.StringWriter; 5
6 import javax.servlet.jsp.JspException; 7 import javax.servlet.jsp.SkipPageException; 8 import javax.servlet.jsp.tagext.JspFragment; 9 import javax.servlet.jsp.tagext.SimpleTagSupport; 10 //控制標簽余下的jsp不執行
11 public class SimpleTagDemo4 extends SimpleTagSupport{ 12
13 @Override 14 public void doTag() throws JspException, IOException { 15 throw new SkipPageException();//只用向jsp頁面拋出這個異常,余下的jsp不會執行
16
17 } 18 }
-
標簽聲明:
1 <tag>
2 <name>demo4</name>
3 <tag-class>com.web.simpletag.SimpleTagDemo4</tag-class>
4 <body-content>empty</body-content><!-- 標簽體為空 -->
5 </tag>
6
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/simpletag" prefix="simple" %>
3 <simple:demo4></simple:demo4>
4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
5 <html>
6 <head>
7 <title>My JSP '1.jsp' starting page</title>
8 </head>
9
10 <body>
11
12 </body>
13 </html>
-
5、開發帶屬性的標簽
在tld文件中描述屬性
-
標簽實現類:
1 package com.web.simpletag; 2
3 import java.io.IOException; 4 import java.io.StringWriter; 5 import java.util.Date; 6
7 import javax.servlet.jsp.JspException; 8 import javax.servlet.jsp.SkipPageException; 9 import javax.servlet.jsp.tagext.JspFragment; 10 import javax.servlet.jsp.tagext.SimpleTagSupport; 11 //帶屬性的標簽
12 public class SimpleTagDemo5 extends SimpleTagSupport{ 13 private int count; 14 private Date date;//jsp只支持8種數據類型的轉換
15
16 public void setCount(int count) { 17 this.count = count; 18 } 19 public void setDate(Date date) { 20 this.date = date; 21 } 22
23 @Override 24 public void doTag() throws JspException, IOException { 25 //得到標簽體
26 JspFragment jf = this.getJspBody(); 27 //輸出日期
28 this.getJspContext().getOut().write(date.toLocaleString()); 29 for(int i=0;i<count;i++){ 30 jf.invoke(null); 31 } 32 } 33 }
-
標簽聲明:
1 <tag>
2 <name>demo5</name>
3 <tag-class>com.web.simpletag.SimpleTagDemo5</tag-class>
4 <body-content>scriptless</body-content><!-- 標簽體為空 -->
5 <attribute> 6 <name>count</name> 7 <required>true</required> 8 <rtexprvalue>true</rtexprvalue><!-- true允許動態賦值 如用el表達式或者腳本表達式賦值--> 9 </attribute> 10 <attribute> 11 <name>date</name> 12 <required>true</required> 13 <rtexprvalue>true</rtexprvalue><!-- true允許動態賦值 如用el表達式或者腳本表達式賦值--> 14 </attribute>
15 </tag>
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/simpletag" prefix="simple" %>
3
4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
5 <html>
6 <head>
7 <title>My JSP '1.jsp' starting page</title>
8 </head>
9
10 <body>
11 <simple:demo5 count="5" date="<%= new Date() %>">
12 aaaaaa 13 </simple:demo5>
14 </body>
15 </html>
6、SimpleTag接口執行順序
7、JspFragment類詳解
8、invoke方法詳解
六、jstl標簽庫
1、c:out標簽
1 <br/>-------------------c:out---------------------------<br/>
2 <%
3 request.setAttribute("data", "bbb"); 4 %>
5 <c:out value="${data}" default="aaaaa" escapeXml="true"></c:out>
2、c:set標簽
1 br/>-------------------c:set可以操作給各個域 javabean Map集合的屬性---------------------------<br/>
2 <!-- 操作域里面的屬性 -->
3 <c:set var="data" value="xxxx" scope="page"/>
4 ${data } 5
6 <!-- 操作javabean的屬性 -->
7 <%
8 Person p = new Person(); 9 request.setAttribute("p", p); 10 %>
11 <c:set property="name" value="xxxx" target="${p }"/>
12 ${p.name } 13
14 <!-- 操作Map集合 -->
15
16 <%
17 Map map = new HashMap(); 18 request.setAttribute("map",map); 19 %>
20 <c:set property="dd" value="aaaa" target="${map }"></c:set>
21 ${map.dd } 22
3、c:remove標簽
4、c:catch標簽
1 <br/>-------------------c:catch---------------------------<br/>
2 <c:catch var="myex">
3 <%
4 int x = 1/0; 5 %>
6 </c:catch>
7
8 ${myex.message}
4、c:if標簽
1 <br/>-------------------c:if---------------------------<br/>
2
3 <c:if var="aaa" test="${user==null}" scope="page">
4 aaaa 5 </c:if>
6 ${aaa }
<c:if標簽>只有滿足test表達式的條件才會執行標簽體
5、c:choose標簽
6、c:forEach標簽
<% List list = new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("dddd"); request.setAttribute("list",list); %>
<c:forEach var="str" items="${list}"> ${str } </c:forEach>
<br/>
<c:forEach var="num" begin="1" end="9" step="1"> ${num } </c:forEach>
<c:forEach>實現表格間色顯示
1 <br/>-------------------c:foreach實現表格間色顯示---------------------------<br/>
2
3 <%
4 list = new ArrayList(); 5 list.add("aaa"); 6 list.add("bbb"); 7 list.add("ccc"); 8 list.add("dddd"); 9 list.add("eeee"); 10 list.add("ffff"); 11 list.add("gggg"); 12 list.add("hhhh"); 13 list.add("kkkkk"); 14 request.setAttribute("list",list); 15 %>
16 <%--${status }獲取到了一個對象,這個對象記住了當前是第幾次迭代 --%>
17
18 <style>
19 .odd{background-color: #FF99FF;}
20 .even{background-color: #FF6633;}
21 tr:hover{background-color: #0000FF;}
22 </style>
23
24 <table border="1" width="20%">
25 <c:forEach var="str" items="${list}" varStatus="status">
26 <tr class="${status.count%2==0?'even':'odd' }"> <!--根據基偶給class賦值 條件表達式-->
27 <td>${str }</td>
28 </tr>
29 </c:forEach>
30 </table>
網頁源代碼:
1 <br/>-------------------c:foreach實現表格間色顯示---------------------------<br/>
2
3
4
5
6 <style>
7 .odd{background-color: #FF99FF;}
8 .even{background-color: #FF6633;}
9 tr:hover{background-color: #0000FF;}
10 </style>
11
12 <table border="1" width="20%">
13
14 <tr class="odd">
15 <td>aaa</td>
16 </tr>
17
18 <tr class="even">
19 <td>bbb</td>
20 </tr>
21
22 <tr class="odd">
23 <td>ccc</td>
24 </tr>
25
26 <tr class="even">
27 <td>dddd</td>
28 </tr>
29
30 <tr class="odd">
31 <td>eeee</td>
32 </tr>
33
34 <tr class="even">
35 <td>ffff</td>
36 </tr>
37
38 <tr class="odd">
39 <td>gggg</td>
40 </tr>
41
42 <tr class="even">
43 <td>hhhh</td>
44 </tr>
45
46 <tr class="odd">
47 <td>kkkkk</td>
48 </tr>
49
50 </table>
效果:
7、c:url標簽
構造url地址
1 <br/>-------------------c:url標簽---------------------------<br/>
2 <!-- 構造url地址 -->
3 <c:url var="url" value="/day11/xxxx"></c:url>
4 <a href="${url }">購買</a>
5
網頁源代碼:
如果url標簽不帶var屬性,就會直接把構造地址輸出給瀏覽器,因為沒有保存,例如
1 <c:url value="/day11/xxxx"></c:url>
2 <a href="${url }">購買</a>
不帶var屬性的用途:獲取路徑
1 <a href='<c:url value="/index.jsp" />'>購買</a>
以前是通過pageContext.request.contextPath獲取路徑
構造地址的時候通過<c:param>附帶參數,如果參數有中文,將自動對參數進行URL編碼,原來的做法是:
<a href="ds.jsp?url=<%=java.net.URLEncoder.encode("編碼的是這里","GB2312")%>">點擊這里
1 <c:url var="url" value="/index.jsp">
2 <c:param name="name" value="中國"></c:param>
3 </c:url>
4 <a href="${url }">購買</a>
網頁源代碼:
8、c:redirect標簽
七、標簽案例
1、開發防盜鏈標簽
需求分析:如果用戶不是通過本網站的首頁通過點擊超鏈接來訪問某一個頁面,則強制控制用戶先跳轉到首頁
-
標簽實現類:RefererTag.java
1 package com.web.example; 2
3 import java.io.IOException; 4
5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import javax.servlet.jsp.JspException; 8 import javax.servlet.jsp.PageContext; 9 import javax.servlet.jsp.SkipPageException; 10 import javax.servlet.jsp.tagext.SimpleTagSupport; 11 //開發防盜鏈標簽
12 public class RefererTag extends SimpleTagSupport { 13 private String site; 14 public void setSite(String site) { 15 this.site = site; 16 } 17
18 public void setPage(String page) { 19 this.page = page; 20 } 21
22 private String page; 23
24 @Override 25 public void doTag() throws JspException, IOException { 26 //得到pageContext對象
27 PageContext pageContext = (PageContext) this.getJspContext(); 28 //得到request對象
29 HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); 30 //得到response對象
31 HttpServletResponse response = (HttpServletResponse) pageContext.getResponse(); 32
33 //得到來訪者的referer
34 String referer = request.getHeader("referer"); 35 System.out.println(referer); 36
37 //如果是盜鏈
38 if(referer==null||!referer.startsWith(site)){ 39 if(page.startsWith(request.getContextPath())){ 40 //如果page是以/day11開頭 41 //跳轉
42 response.sendRedirect(page); 43 }else if (page.startsWith("/")) { 44 //如果page以/開頭
45 response.sendRedirect(request.getContextPath()+page); 46 }else { 47 //如果page是index.jsp形式
48 response.sendRedirect(request.getContextPath()+"/"+page); 49 } 50
51 //盜鏈的話余下的jsp不執行,通過拋出異常
52 throw new SkipPageException(); 53 } 54 } 55 }
-
標簽聲明:
1 <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
4 version="2.0">
5
6 <description>A tag library exercising SimpleTag handlers.</description>
7 <tlib-version>1.0</tlib-version>
8 <short-name>e</short-name>
9 <uri>/example</uri>
10 <tag>
11 <name>referer</name>
12 <tag-class>com.web.example.RefererTag</tag-class>
13 <body-content>empty</body-content>
14
15 <attribute>
16 <name>site</name>
17 <required>true</required>
18 <rtexprvalue>true</rtexprvalue>
19 </attribute>
20
21 <attribute>
22 <name>page</name>
23 <required>true</required>
24 <rtexprvalue>true</rtexprvalue>
25 </attribute>
26 </tag>
27
28
29 </taglib>
-
首頁:index.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2
3
4 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
5 <html>
6 <head>
7 </head>
8
9 <body>
10 <a href="/day11/example/1.jsp">點我看鳳姐</a>
11 </body>
12 </html>
-
目標頁面:1.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/example" prefix="e" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <e:referer site="http://localhost" page="index.jsp"/>
5 <html>
6 <head>
7 <title>My JSP '1.jsp' starting page</title>
8 </head>
9
10 <body>
11 鳳姐。。。。。。。。。。。。。。。。。鳳姐 12 </body>
13 </html>
site屬性表示用戶是否從site指定的地址跳轉過來的,如果不是在標簽實現類中跳轉到page指定的頁面。
2、開發c:if標簽:jstl核心標簽庫有
-
標簽處理器類:IfTag.java
1 package com.web.example; 2
3 import java.io.IOException; 4
5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.tagext.SimpleTagSupport; 7 //開發cf標簽
8 public class IfTag extends SimpleTagSupport { 9 private boolean test; 10
11 public void setTest(boolean test) { 12 this.test = test; 13 } 14
15 @Override 16 public void doTag() throws JspException, IOException { 17 if(test){ 18 this.getJspBody().invoke(null); 19 } 20 } 21 }
-
標簽聲明:
1 <tag>
2 <name>if</name>
3 <tag-class>com.web.example.IfTag</tag-class>
4 <body-content>scriptless</body-content>
5
6 <attribute>
7 <name>test</name>
8 <required>true</required>
9 <rtexprvalue>true</rtexprvalue>
10 </attribute>
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/example" prefix="c" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>My JSP '1.jsp' starting page</title>
7 </head>
8
9 <body>
10 <c:if test="${user==null }">
11 aaaa 12 </c:if>
13 </body>
14 </html>
3、開發c:when和c:otherwise標簽
-
父類標簽處理器類:ChooseTag.java
1 package com.web.example; 2
3 import java.io.IOException; 4
5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.tagext.SimpleTagSupport; 7
8 //父標簽處理類
9 public class ChooseTag extends SimpleTagSupport { 10
11 private boolean isDo;//記錄是否被修改過
12
13 public boolean isDo() { 14 return isDo; 15 } 16
17 public void setDo(boolean isDo) { 18 this.isDo = isDo; 19 } 20
21
22 }
-
c:when標簽實現類:WhenTag.java
1 package com.web.example; 2
3 import java.io.IOException; 4
5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.tagext.SimpleTagSupport; 7
8 import sun.reflect.generics.tree.Tree; 9 //c:when標簽處理器類
10 public class WhenTag extends SimpleTagSupport { 11 private boolean test; 12
13 public void setTest(boolean test) { 14 this.test = test; 15 } 16
17 @Override 18 public void doTag() throws JspException, IOException { 19 //得到父類標簽
20 ChooseTag parent = (ChooseTag) this.getParent(); 21 if(test && !parent.isDo()){ 22 this.getJspBody().invoke(null); 23 //把isDo置為true
24 parent.setDo(true); 25 } 26 } 27 }
-
c:otherwise標簽實現類:OtherWiseTag.java
1 package com.web.example; 2
3 import java.io.IOException; 4
5 import javax.servlet.jsp.JspException; 6 import javax.servlet.jsp.tagext.SimpleTagSupport; 7 import javax.swing.text.html.HTMLDocument.HTMLReader.ParagraphAction; 8
9 public class OtherWiseTag extends SimpleTagSupport { 10
11 @Override 12 public void doTag() throws JspException, IOException { 13 //得到父標簽
14 ChooseTag parent = (ChooseTag) this.getParent(); 15 if(!parent.isDo()){ 16 this.getJspBody().invoke(null); 17 parent.setDo(true); 18 } 19 } 20 }
-
標簽聲明:
1 <tag>
2 <name>choose</name>
3 <tag-class>com.web.example.ChooseTag</tag-class>
4 <body-content>scriptless</body-content>//標簽體內容是子標簽
5 </tag>
6
7 <tag>
8 <name>when</name>
9 <tag-class>com.web.example.WhenTag</tag-class>
10 <body-content>scriptless</body-content>
11 <attribute>
12 <name>test</name>
13 <required>true</required>
14 <rtexprvalue>true</rtexprvalue>
15 </attribute>
16 </tag>
17
18 <tag>
19 <name>otherwise</name>
20 <tag-class>com.web.example.OtherWiseTag</tag-class>
21 <body-content>scriptless</body-content>
22 </tag>
23
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/example" prefix="c" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>My JSP '1.jsp' starting page</title>
7 </head>
8
9 <body>
10 <c:choose>
11 <c:when test="${user==null }">
12 aaaa 13 </c:when>
14 <c:otherwise>
15 bbbb 16 </c:otherwise>
17 </c:choose>
18 </body>
19 </html>
4、開發c:foreach標簽
-
sun公司開發的<c:forEach>部分源碼:
1 protected ForEachIterator supportedTypeForEachIterator(Object o) 2 throws JspTagException 3 { 4 ForEachIterator items; 5 if (o instanceof Object[]) 6 items = toForEachIterator((Object[])o); 7 else if (o instanceof boolean[]) 8 items = toForEachIterator((boolean[])o); 9 else if (o instanceof byte[]) 10 items = toForEachIterator((byte[])o); 11 else if (o instanceof char[]) 12 items = toForEachIterator((char[])o); 13 else if (o instanceof short[]) 14 items = toForEachIterator((short[])o); 15 else if (o instanceof int[]) 16 items = toForEachIterator((int[])o); 17 else if (o instanceof long[]) 18 items = toForEachIterator((long[])o); 19 else if (o instanceof float[]) 20 items = toForEachIterator((float[])o); 21 else if (o instanceof double[]) 22 items = toForEachIterator((double[])o); 23 else if (o instanceof Collection) 24 items = toForEachIterator((Collection)o); 25 else if (o instanceof Iterator) 26 items = toForEachIterator((Iterator)o); 27 else if (o instanceof Enumeration) 28 items = toForEachIterator((Enumeration)o); 29 else if (o instanceof Map) { 30 items = toForEachIterator((Map)o); 31 } 32 else if (o instanceof String) 33 items = toForEachIterator((String)o); 34 else
35 items = toForEachIterator(o); 36
37 return items; 38 }
-
標簽實現類:ForeachTag.java
1 package com.web.example; 2 import java.util.ArrayList; 3 import java.util.Collection; 4 import java.util.Iterator; 5 import java.util.List; 6 import java.util.Map; 7 import java.io.IOException; 8 import java.lang.reflect.Array; 9
10 import javax.servlet.jsp.JspException; 11 import javax.servlet.jsp.tagext.SimpleTagSupport; 12 public class ForeachTag extends SimpleTagSupport { 13 private Object items;//保存需要迭代的數據
14 private String var;//每次迭代的關鍵字聲明為String類型
15 private Collection collection;//把所有類型的數據轉成單列集合
16 public void setVar(String var) { 17 this.var = var; 18 } 19 public void setItems(Object items) { 20 this.items = items; 21 if(items instanceof Collection){//判斷items是否是單列集合
22 collection = (Collection) items; 23 } 24
25 if(items instanceof Map){ 26 Map map = (Map) items; 27 collection = map.entrySet();//set entrySet是單列集合
28 } 29
30 //八種基本數據類型數組處理,用到relect反射包里面的Array對所有類型的進行處理 31 if(items.getClass().isArray()){//Class類里面有一個方法判斷是否是數組 32 this.collection = new ArrayList(); 33 int length = Array.getLength(items);//reflect包中Array的方法 34 //迭代 35 for(int i=0;i<length;i++){ 36 Object value = Array.get(items, i); 37 collection.add(value); 38 } 39 } 40
41 } 42 @Override 43 public void doTag() throws JspException, IOException { 44 Iterator it = this.collection.iterator();//獲取迭代器 45 while (it.hasNext()) { 46 Object value = it.next();//取出每個元素 47 this.getJspContext().setAttribute(var, value);//每次迭代覆蓋 48 this.getJspBody().invoke(null); 49 } 50 } 51 }
-
標簽聲明:
1 <tag>
2 <name>foreach</name>
3 <tag-class>com.web.example.ForeachTag</tag-class>
4 <body-content>scriptless</body-content>
5 <attribute>
6 <name>var</name><!-- 每次迭代的標記 -->
7 <required>true</required>
8 <rtexprvalue>false</rtexprvalue>
9 </attribute>
10 <attribute>
11 <name>items</name>
12 <required>true</required>
13 <rtexprvalue>true</rtexprvalue>
14 </attribute>
15 </tag>
-
使用標簽:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/example" prefix="c" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>My JSP '1.jsp' starting page</title>
7 </head>
8
9 <body>
10 <%
11 List list = new ArrayList(); 12 list.add("aaa"); 13 list.add("bbb"); 14 list.add("ccc"); 15 list.add("ddd"); 16 list.add("eee"); 17 request.setAttribute("list", list); 18 %>
19 <c:foreach var="str" items="${list }">
20 ${str } 21 </c:foreach>
22 <br/>-------------------------<br/>
23 <%
24 Map map = new HashMap(); 25 map.put("aa", "1111"); 26 map.put("bb", "2222"); 27 map.put("cc", "3333"); 28 map.put("dd", "4444"); 29 map.put("ee", "5555"); 30 request.setAttribute("map",map); 31 %>
32 <c:foreach items="${map }" var="entry">
33 ${entry.key } = ${entry.value } 34 </c:foreach>
35
36 <br/>---------------------------<br/>
37 <%
38 Integer num[] = {1,2,3}; 39 request.setAttribute("num",num); 40 %>
41
42 <c:foreach items="${num }" var="i">
43 ${i } 44 </c:foreach>
45
46 <br/>----------------------------<br/>
47
48 <%
49 int arr[] = {1,2,3}; 50 request.setAttribute("arr", arr); 51 %>
52 <c:foreach items="${arr}" var="i">
53 ${i } 54
55 </c:foreach>
56
57 <br/>------------------<br/>
58 <%
59 boolean b[] = {true,false,true,true}; 60 request.setAttribute("b", b); 61 %>
62
63 <c:foreach items="${b }" var="i">
64 ${i} 65 </c:foreach>
66
67 <br/>------------------------------<br/>
68 <%
69 String s[] = {"aaa","bbb","cccc"}; 70 request.setAttribute("s",s); 71 %>
72 <c:foreach items="${s }" var="i">
73 ${i} 74 </c:foreach>
75
76 <br/>-------------------------<br/>
77 <%
78 double d[] = {2.0,3.0,4.0}; 79 request.setAttribute("d", d); 80 %>
81 <c:foreach items="${d }" var="i">
82 ${i} 83 </c:foreach>
84
85
86 <br/>-------------------------<br/>
87 <%
88 float f[] = {2,3,4}; 89 request.setAttribute("f", f); 90 %>
91 <c:foreach items="${f }" var="i">
92 ${i} 93 </c:foreach>
94
95
96 <br/>-------------------------<br/>
97 <%
98 char c[] = {'c','c','d'};
99 request.setAttribute("c", c); 100 %>
101 <c:foreach items="${c }" var="i">
102 ${i} 103 </c:foreach>
104 </body>
105 </html>
通過對比可以發現,已經對要迭代的數據是八種基本數據類型的數據的代碼進行了優化如下:
1 //八種基本數據類型數組處理,用到relect反射包里面的Array對所有類型的進行處理
2 if(items.getClass().isArray()){//Class類里面有一個方法判斷是否是數組
3 this.collection = new ArrayList();
4 int length = Array.getLength(items);//reflect包中Array的方法
5 //迭代
6 for(int i=0;i<length;i++){
7 Object value = Array.get(items, i);
8 collection.add(value);
9 }
10 }
5、開發html轉義標簽
-
標簽實現類:FilterTag.java
1 package com.web.example; 2
3 import java.io.IOException; 4 import java.io.StringWriter; 5
6 import javax.servlet.jsp.JspException; 7 import javax.servlet.jsp.tagext.JspFragment; 8 import javax.servlet.jsp.tagext.SimpleTagSupport; 9 //開發html轉義標簽
10 public class FilterTag extends SimpleTagSupport { 11 @Override 12 public void doTag() throws JspException, IOException { 13 //緩沖流
14 StringWriter sw = new StringWriter(); 15 //得到標簽體
16 JspFragment jf = this.getJspBody(); 17 //執行標簽體,把標簽體內容緩存到緩沖流中
18 jf.invoke(sw); 19 //從緩沖流中取出標簽體內容進行轉義
20 String content = sw.getBuffer().toString(); 21 content = filter(content); 22 //輸出給瀏覽器
23 this.getJspContext().getOut().write(content); 24
25 } 26
27 //tomcat轉義源碼 28 public static String filter(String message) { 29 if (message == null) 30 return (null); 31 32 char content[] = new char[message.length()]; 33 message.getChars(0, message.length(), content, 0); 34 StringBuilder result = new StringBuilder(content.length + 50); 35 for (int i = 0; i < content.length; i++) { 36 switch (content[i]) { 37 case '<': 38 result.append("<"); 39 break; 40 case '>': 41 result.append(">"); 42 break; 43 case '&': 44 result.append("&"); 45 break; 46 case '"': 47 result.append("""); 48 break; 49 default: 50 result.append(content[i]); 51 } 52 } 53 return (result.toString()); 54 55 } 56 }
-
標簽聲明
1 <tag>
2 <name>filter</name>
3 <tag-class>com.web.example.FilterTag</tag-class>
4 </tag>
-
使用標簽
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@taglib uri="/example" prefix="c" %>
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>轉義標簽</title>
7 </head>
8
9 <body>
10 <c:filter>
11 <a href="/day11/index.jsp"><!--把標簽按原樣輸出-->
12 </c:filter>
13 </body>
14 </
-
效果
6、將自定義開發的標簽打包成jar包
新建一個java工程
把標簽處理類放在src目錄下:
新建一個META-INF目錄,存放標簽描述文件:example.tld
打成jar包
使用時直接把jar文件導入到lib目錄下即可,打包的時候報錯不用理會,因為源代碼中用到的jsp、servlet的API沒有引入。