一、自定义标签简介
1、自定义标签主要用于移除Jsp页面中的java代码,jsp禁止出现一行java脚本.
2、使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤:
•编写一个实现Tag接口的Java类(标签处理器类).
•编写标签库描述符(tld)文件,在tld文件中对标签处理器类进行描述.
3、快速入门:使用标签输出客户机IP
//java类 public class ViewPortTag extends TagSupport{ @Override public int doStartTag() throws JspException { HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest(); JspWriter out = this.pageContext.getOut(); int port = request.getRemotePort(); try { out.print(port); } catch (IOException e) { throw new RuntimeException(e);//让调用者知道报错 } return super.doStartTag(); } }
<!--ku6.tld --> <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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <description>A tag library exercising SimpleTag handlers.</description> <tlib-version>1.0</tlib-version> <short-name>SimpleTagLibrary</short-name> <uri>http://www.hgnc.net/jsp2-tag</uri> <tag> <description>show client IP</description> <name>ViewPortTag</name> <tag-class>com.ku6.web.tag.ViewPortTag</tag-class> <body-content>empty</body-content> </tag> </taglib>
<!-- jsp --> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="ku6" uri="http://www.hgnc.net/jsp2-tag"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Insert title here</title> </head> <body> port:<ku6:ViewPortTag/> </body> </html>
查看编译后的jsp源码
package org.apache.jsp; import com.ku6.web.tag.ViewPortTag; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.el.ExpressionFactory; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspApplicationContext; import javax.servlet.jsp.JspFactory; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.SkipPageException; import org.apache.jasper.runtime.HttpJspBase; import org.apache.jasper.runtime.InstanceManagerFactory; import org.apache.jasper.runtime.JspSourceDependent; import org.apache.jasper.runtime.TagHandlerPool; import org.apache.tomcat.InstanceManager; public final class NewFile_jsp extends HttpJspBase implements JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static Map<String, Long> _jspx_dependants = new HashMap(1); private TagHandlerPool _005fjspx_005ftagPool_005fku6_005fViewPortTag_005fnobody; private ExpressionFactory _el_expressionfactory; private InstanceManager _jsp_instancemanager; static { _jspx_dependants.put("/WEB-INF/ku6.tld", Long.valueOf(1448265099457L)); } public Map<String, Long> getDependants() { return _jspx_dependants; } public void _jspInit() { this._005fjspx_005ftagPool_005fku6_005fViewPortTag_005fnobody = TagHandlerPool.getTagHandlerPool(getServletConfig()); this._el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); this._jsp_instancemanager = InstanceManagerFactory.getInstanceManager(getServletConfig()); } public void _jspDestroy() { this._005fjspx_005ftagPool_005fku6_005fViewPortTag_005fnobody.release(); } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { JspWriter out = null; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html; charset=UTF-8"); PageContext pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; pageContext.getServletContext(); pageContext.getServletConfig(); pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\r\n"); out.write("\r\n"); out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n"); out.write("<html>\r\n"); out.write("<head>\r\n"); out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\r\n"); out.write("<title>Insert title here</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n"); out.write("\tport:"); if (_jspx_meth_ku6_005fViewPortTag_005f0(_jspx_page_context)) return; out.write(" \r\n"); out.write("</body>\r\n"); out.write("</html>"); } catch (Throwable t) { if (!(t instanceof SkipPageException)) { out = _jspx_out; if ((out != null) && (out.getBufferSize() != 0)) try { out.clearBuffer(); } catch (IOException localIOException) { } if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } private boolean _jspx_meth_ku6_005fViewPortTag_005f0(PageContext _jspx_page_context) throws Throwable { _jspx_page_context.getOut(); ViewPortTag _jspx_th_ku6_005fViewPortTag_005f0 = (ViewPortTag)this._005fjspx_005ftagPool_005fku6_005fViewPortTag_005fnobody.get(ViewPortTag.class); _jspx_th_ku6_005fViewPortTag_005f0.setPageContext(_jspx_page_context); _jspx_th_ku6_005fViewPortTag_005f0.setParent(null); _jspx_th_ku6_005fViewPortTag_005f0.doStartTag(); if (_jspx_th_ku6_005fViewPortTag_005f0.doEndTag() == 5) { this._005fjspx_005ftagPool_005fku6_005fViewPortTag_005fnobody.reuse(_jspx_th_ku6_005fViewPortTag_005f0); return true; } this._005fjspx_005ftagPool_005fku6_005fViewPortTag_005fnobody.reuse(_jspx_th_ku6_005fViewPortTag_005f0); return false; } }
二、Tag接口的执行流程
JSP引擎遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法.
1、public void setPageContext(PageContext pc), JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面的pageContext对象传递给标签处理器,标签处理器以后可以通过这个pageContext对象与JSP页面进行通信.
2、public void setParent(Tag t),setPageContext方法执行完后,WEB容器接着调用的setParent方法将当前标签的父标签传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null.
3、public int doStartTag(),调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会调用标签处理器的doStartTag方法.
4、public int doEndTag(),WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器会去调用标签处理器的doEndTag方法.
5、public void release(),通常WEB容器执行完自定义标签后,标签处理器会驻留在内存中,为其它请求服务器,直至停止web应用时,web容器才会调用release方法.
三、自定义标签功能扩展
自定义标签除了可以移除jsp页面java代码外,它也可以实现以下一些逻辑功能:
•控制jsp页面某一部分内容是否执行.
•控制整个jsp页面是否执行.
•控制jsp页面内容重复执行.
•修改jsp页面内容输出.
具体的代码写法,略,基本不会用到.
四、简单标签
由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广, SUN公司为降低标签技术的学习难度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口来实现标签的功能.实现SimpleTag接口的标签通常称为简单标签.
**简单标签和传统标签的原理相同,只是api不同而已,实际开发中不会让自己写标签,会用就可以.
五、JSTL标签库 *重点
1、<c:out>标签
<c:out> 标签用于输出一段文本内容到pageContext对象当前保存的“out”对象中.
例:
<c:out value="aabbcc<br/>" escapeXml="false"></c:out> <c:out value="<a href=‘‘>点点</a>" escapeXml="true"></c:out> <% request.setAttribute("data",null); %> <c:out default="bbbbbbbbbbbbb" value="${data}"></c:out>
2、<c:set>标签
<c:set>标签用于把某一个对象存在指定的域范围内,或者设置Web域中的java.util.Map类型的属性对象或JavaBean类型的属性对象的属性.
*只要在标签中看到Var就表示把当前标签的执行结果以var定义的名称为关键字存在某个域里面.
<c:set var="dd" value="ddvalue" scope="page"/> ${dd}<br/> <% Map map=new HashMap(); request.setAttribute("map",map); %> <c:set property="dd" value="xxx" target="${map}" /> ${map.dd }<br/> <% Person p=new Person(); request.setAttribute("p",p); %> <c:set property="name" value="namevalue" target="${p}"></c:set> <c:out value="${p.name}"></c:out>
3、<c:remove>标签
<c:remove>标签用于删除各种Web域中的属性.
<c:remove var="varName" [scope="{page|request|session|application}"] />
4、<c:catch>标签
<c:catch>标签用于捕获嵌套在标签体中的内容抛出的异常,其语法格式如下:
<c:catch [var="varName"]>nested actions</c:catch>
var属性用于标识<c:catch>标签捕获的异常对象,它将保存在page这个Web域中.例:
<c:catch var="myex"> <% int i=10/0; %> </c:catch> <c:out value="${myex}" /><br /> <c:out value="${myex.message}" /><br /> <c:out value="${myex.cause}" /><br /> <c:out value="${myex.stackTrace}" />
5、<c:if>标签
<c:if test=“”>标签可以构造简单的“if-then”结构的条件表达式.
例:
<c:if var="aaa" test="${user==null}" scope="page"></c:if> ${aaa }
6、<c:choose>标签
<c:choose>标签用于指定多个条件选择的组合边界,它必须与<c:when>和<c:otherwise>标签一起使用.使用<c:choose>,<c:when>和<c:otherwise>三个标签,可以构造类似 “if-else if-else” 的复杂条件判断结构.例:
<c:set value="2" var="count" /> <c:choose> <c:when test="${count == 0}"> 对不起,没有符合您要求的记录. </c:when> <c:otherwise> 符合您要求的记录共有${count}条. </c:otherwise> </c:choose>
7、<c:forEach>标签
<c:forEach>标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容.
ps:上面没有列出varStatus.
例1,没有items:
<c:forEach var="i" begin="1" end="9" step="1" > ${i} </c:forEach>
例2,实现表格隔行变色:
<% List list=new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd"); request.setAttribute("list",list); %> <style> .odd{background-color: blue;} .even{background-color: red;} tr:hover{background-color: green;} //如果不支持鼠标放上去变色,可从tomact默认网页上拷头<!DOCTYPE html> </style> <table> <c:forEach var="str" items="${list}" varStatus="status"> <tr class="${status.count%2==0?‘even‘:‘odd‘}"><td> ${status} ::: ${str }</td></tr>//el表达式可以写各种java表达式 </c:forEach> </table>
例3,varStatus的属性:
<% String atts[] = new String [5]; atts[0]="hello"; atts[1]="this"; atts[2]="is"; atts[3]="a"; atts[4]="pen"; request.setAttribute("atts", atts); %> <c:forEach items="${atts}" var="item" varStatus="s"> <c:out value="${item}"/>的四种属性: index:${s.index}</br> count:${s.count}</br> first:${s.first}</br> last:${s.last}</br> </c:forEach>
8、<c:url>标签 ,<c:param>标签 , *重点
1><c:url>标签用于在JSP页面中构造一个URL地址,其主要目的是实现URL重写.URL重写就是将会话标识号(sessionId)以参数形式附加在URL地址后面.
2>在JSP页面进行URL的相关操作时,经常要在URL地址后面附加一些参数.<c:param>标签可以嵌套在<c:url>或<c:redirect>标签内,为这些标签所使用的URL地址附加参数.<c:param>标签在为一个URL地址附加参数时,将自动对参数值进行URL编码,例如,如果传递的参数值为“中国”,则将其转换为“%d6%d0%b9%fa”后再附加到URL地址后面,这也就是使用<c:param>标签的最大好处.
例:
<c:url var="url" value="/index.jsp"> <c:param name="name" value="中国"></c:param> </c:url> <a href="${url }">购买</a>//会自动补全路径
ps:若果刷新页面,发现sessionId没有传递给客户端,因为服务器发现客户端没有禁ip后,第二次就不会在传递sessionId.
9、<c:redirect>标签,用于实现请求重定向
10、forTokens标签,分割字符串
<% String data="aa,bb,cc,dd"; request.setAttribute("data",data); %> <c:forTokens items="${data}" delims="\," var="c">${c}