一、自定义标签开发库简介
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没有引入。