一、引入标签
其实在JSP中我们已经使用过了几个标签,比如<jsp:forward>、<jsp:include>等;这些标签都是预先定义好的,如果我们需要自定义标签,就需要学习标签编程。
标签编程的优点就是灵活性+封装性。
灵活性体现在属性的赋值上,可以赋任意值。比如<jsp:forward page="A"> //A处可以赋任意的URL;
封装性体现在内部的行为的封装,因为标签是用一个类实现的,因此类的方法中能够包含任意复杂的动作。
因此标签是为了能够在JSP中使用尽可能少的Scriptlet;
比如:
- <table>
- <%
- for(int i=0;i<10;i++){
- %>
- <tr>
- <%
- for(int j=0;j<10;j++){
- %>
- <td><%=i*j%></td>
- <%
- }
- %>
- </tr>
- <%
- }
- %>
- </table>
这个代码非常混乱,但是如果通过标签,从这段代码都封装在一个标签里,则代码就清晰了很多。
接下来是我通过标签封装后的JSP页面效果;
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <%@ taglib prefix="xiazdong" uri="xiazdong"%>
- <html>
- <head>
- <title></title>
- </head>
- <body>
- <xiazdong:table row="5" col="3"/>
- </body>
- </html>
是不是大大缩短了呢??再来看看我在背后干了什么。。。。
TableTagSupport.java
- package org.tagext;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.jsp.*;
- public class TableTagSupport extends TagSupport{
- private String row;
- private String col;
- public String getRow(){
- return row;
- }
- public String getCol(){
- return col;
- }
- public void setRow(String row){
- this.row = row;
- }
- public void setCol(String col){
- this.col = col;
- }
- public int doStartTag()throws JspException{
- JspWriter out = super.pageContext.getOut();
- try{
- out.println("<table border=\"3\"> ");
- for(int i=0;i<Integer.parseInt(row);i++){
- out.println("<tr>");
- for(int j=0;j<Integer.parseInt(col);j++){
- out.println("<td>"+i*j+"</td>");
- }
- out.println("</tr>");
- }
- out.println("</table>");
- }
- catch(Exception e){}
- return TagSupport.SKIP_BODY;
- }
- }
是不是很神奇。。。那接下来就看看实现的过程吧。
注意,在编写标签之前,必须把tomcat\lib中的jsp-api.jar文件配置在CLASSPATH中才可以;
二、基本标签编写
1、TagSupport类
如果要编写一个标签类,则必须继承javax.servlet.jsp.tagext.TagSupport;
TagSupport中提供了很多常用方法:
(1) public int doStartTag()throws JspException; // 标签开始时调用
能够返回SKIP_BODY(跳过标签体)、EVAL_BODY_INCLUDE(执行标签体)
(2) public int doEndTag()throws JspException; // 标签结束时调用
能够返回SKIP_PAGE(立刻停止执行)、EVAL_PAGE(JSP正常运行完毕);
(3) int SKIP_BODY; // 跳过标签体
(4) int EVAL_BODY_INCLUDE; //执行标签体
(5) int EVAL_BODY_AGAIN; // 重复执行标签体,主要是因为集合迭代输出,只能在doAfterBody中使用;
(6) public int doAfterBody()throws JspException; // 执行完一次标签体后调用的函数;
能够返回SKIP_BODY(结束标签体)、EVAL_BODY_AGAIN(重复执行标签体)
(7) JspWriter out = super.pageContext.getOut();//获取向网页输出的输出流;
举例讲述这些函数和常量代表什么意思:
- <xiazdong:hello> <!--标签头 -->
- <h3><%="xiazdong"%></h3> <!-- 标签体-->
- </xiazdong:hello> <!-- 标签尾-->
执行流程如下:
(1)doStartTag(); <xiazdong:hello>时调用,如果是EVAL_BODY_INCLUDE,则继续;如果是SKIP_BODY,则执行(4)
(2)执行标签体;
(3)如果实现了doAfterBody,则执行;如果返回SKIP_BODY,则执行(4) ; 如果返回EVAL_BODY_AGAIN,则重复执行doAfterBody;
(4)doEndTag():标签尾调用;
2.制作无属性标签
为了清晰,我们以例子说明。
代码举例1:实现显示Hello world;
1.编写HelloTag.java
- package org.tagext;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.jsp.*;
- public class HelloTag extends TagSupport{
- public int doStartTag()throws JspException{
- JspWriter out = super.pageContext.getOut();
- try{
- out.println("<h3>Hello world!!!</h3>");
- }
- catch(Exception e){}
- return TagSupport.SKIP_BODY;
- }
- }
注意点:
(1)javax.servlet.jsp.tagext.TagSupport,必须记住;
(2)JspWriter out = super.pageContext.getOut();
(3)public int doStartTag()throws JspException;必须记住;
tld文件是标签描述文件,是整个标签编程的核心,用来描述自定义的标签的名字、标签的实现类、是否有标签体、描述属性等;
一个tld文件其实类似于一个标签库,里面能够描述很多标签;每个标签都以
- <tag>
- <name>hello</name> <!--表示标签的名字 类似于<jsp:forward>中的forward-->
- <tag-class>org.tagext.HelloTag</tag-class> <!--标签所在类 -->
- <body-content>empty</body-content> <!--是否存在标签体-->
- </tag>
的形式描述;
*.tld文件的模版如下:(因为tld文件前面这些内容都不是很重要,因此可以直接复制黏贴)
- <?xml version="1.0" encoding="UTF-8" ?>
- <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">
- <tlib-version>1.0</tlib-version>
- //插入tag描述
- </taglib>
3.在web.xml中编写映射
编写映射的目的类似于给一个网页配置一个映射地址,为了方便访问;
比如本来需要访问/a/b/c/d/e/f/g/1.tld,这个路径非常麻烦,但是如果通过映射,我们可以只需要用"a"表示一长串的文件路径及名称;
- <jsp-config>
- <taglib>
- <taglib-uri>xiazdong</taglib-uri>
- <taglib-location>/WEB-INF/classes/xiazdong.tld</taglib-location>
- </taglib>
- </jsp-config>
4.编写JSP页面并使用自定义的标签
<%@ taglib prefix="" uri=""%> prefix类似于<jsp:forward>中的jsp,uri中使用前面所说的映射;
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <%@ taglib prefix="xiazdong" uri="xiazdong"%>
- <html>
- <head>
- <title></title>
- </head>
- <body>
- <h1><xiazdong:hello/></h1>
- </body>
- </html>
3.制作有属性标签
其实制作有属性和制作无属性没有太大区别,
1.需要在原来的HelloTag.java 中加入属性.
如果做形如:<xiazdong:hello id="" format="" />的属性,则需要在HelloTag.java中添加两个属性,id属性和format属性;
形如:
- class HelloTag extends TagSupport
- {
- private String id;
- private String format;
- //setter和getter
- public int doStartTag()throws JspException{}
- }
在用户使用标签,并为id和format属性赋值时,会自动调用setter方法,将HelloTag类中的id和format赋值;
2.在tld文件中添加属性描述:
属性描述形如:
- <body-content>empty</body-content>后面加上
- <attribute>
- <name>name</name> <!--属性姓名 -->
- <required>true</required> <!--属性是否必要 -->
- <rtexprvalue>empty</rtexprvalue> <!--是否支持表达式语言 -->
- </attribute>
代码实例:
HelloTag.java
- package org.tagext;
- import javax.servlet.jsp.tagext.*;
- import javax.servlet.jsp.*;
- public class HelloTag extends TagSupport{
- private String name;
- private String age;
- public String getName(){
- return name;
- }
- public String getAge(){
- return age;
- }
- public void setName(String name){
- this.name = name;
- }
- public void setAge(String age){
- this.age = age;
- }
- public int doStartTag()throws JspException{
- JspWriter out = super.pageContext.getOut();
- try{
- out.println("<h3>姓名:"+name+"</h3>");
- out.println("<h3>年龄:"+age+"</h3>");
- }
- catch(Exception e){}
- return TagSupport.SKIP_BODY;
- }
- }
- <?xml version="1.0" encoding="UTF-8" ?>
- <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">
- <tlib-version>1.0</tlib-version>
- <short-name>x</short-name>
- <tag>
- <name>hello</name>
- <tag-class>org.tagext.HelloTag</tag-class>
- <body-content>empty</body-content>
- <attribute>
- <name>name</name>
- <required>true</required>
- <rtexprvalue>empty</rtexprvalue>
- </attribute>
- <attribute>
- <name>age</name>
- <required>true</required>
- <rtexprvalue>empty</rtexprvalue>
- </attribute>
- </tag>
- </taglib>
HelloTag.jsp
- <%@ page contentType="text/html" pageEncoding="GBK"%>
- <%@ taglib prefix="xiazdong" uri="xiazdong"%>
- <html>
- <head>
- <title></title>
- </head>
- <body>
- <h1><xiazdong:hello name="xiazdong" age="20"/></h1>
- </body>
- </html>