先介绍一些琐碎的概念。
javascript与JSP/Servlet
常用的动态网页技术有CGI(Common Gateway Interface),PHP(Hypertext Preprocessor),ASP(Active Server Pages)和Servlet/JSP(Java Server Pages)。未经服务器端程序处理的纯html属于静态网页。在介绍javascript的书中,常常将javascript定义为动态网页的范畴,实际上html中的javascript代码会被浏览器执行,而不是被服务器端程序执行。javascript其实和java没有关系。javascript用于与浏览器沟通,操作浏览器中的网页画面与行为,也可以通过javascript要求浏览器发送请求给服务器。
所以javascript与servlet/jsp不能直接互动,必须通过HTTP来进行互动,数据交换或请求,响应。服务器会将jsp网页中内嵌的javascript代码原封不动的返回给浏览器,由浏览器执行。对于处理jsp内容的服务器而言,内嵌的javascript跟静态的html标签没有任何区别。
JavaEE
Java EE(Java Platform, Enterprise Edition)。与此对应的还有JavaSE(Java Platform, Standard Edition),JavaME(Java Platform, Micro Edition)。无论是Java EE,Java SE,Java ME,都是业界共同制定的标准,业界代表可参与JCP(Java Community Process)共同参与,审核,投票决定平台应有的组件,特性,应用程序编程接口等,所制定出来的标准以JSR(Java Specification Requests)作为正式标准规范文件,不同的技术解决方案标准规范会给一个编号。在JSR规范的标准下,各个厂商可以各自实现成品,所以同样是web容器,会有不同的厂商的实现产品,而JSR通常也会提供参考实现。
现在我们来继续讨论标签库(Tag library),这也是本篇的主要内容。使用它可以让我们定义自己标签,我们在Servlet&JSP的那些事儿(十)中讨论了jsp的动作元素,其实动作元素本质上就是一段java代码,在jsp页面被转换为servlet时,jsp容器遇到动作元素标签,就会用预先定义的相对应的java代码替代它。自定义标签实际上也是一个实现了特定接口的java类。
标签库API
标签库API存在定义在javax.servlet.jsp.tagex包中。其中主要的接口和类如图1所示。
图1 标签库中主要的接口及类的继承实现关系
自定义标签和其他已有标签一样,有四种形式。
空标签<hello />
带有属性的标签<max attr1="attr1" attr2="attr2" />
带有内容的标签<greeting> hello </greeting>
带有内容和属性的标签<greeting name="shan">hello</greeting>
Tag接口
javax.servlet.jsp.tagext.Tag接口定义了所有传统的标签处理器所要实现的基本方法。包括setPageContext()、setParent()、getParent()等。实现了Tag接口的标签处理器的生命周期如下:
1)容器创建标签处理器实例以后,调用setPageContext()方法设置标签的上下文,然后调用setParent()设置标签的父标签,如果没有,置为null。
2)调用标签处理器的setXXX()方法,设置标签属性(没有属性,直接跳过)
3)调用doStartTag()方法,返回一个EVAL_BODY_INCLUDE或SKIP_BODY。如果返回前者,则将标签输出到当前的输出流,如果返回后者,忽略标签体。
4)调用doEndTag()方法,返回EVAL_PAGE或SKIP_PAGE,抢着表示执行jsp页面剩余部分,后者表示省略jsp页面剩余部分。
5)容器会缓存标签处理器实例,一旦遇到同样的标签,重复使用缓存的标签处理器实例
6)当需要释放标签处理器实例时,调用release()方法释放。
IterationTag接口
javax.servlet.jsp.tagext.IterationTag接口继承自Tag接口,它新增了一个方法和一个用作返回值的常量,用于控制对标签体的重复处理。实现了该接口的标签处理器的声明周期如下:
前三步和实现Tag接口的标签处理器相同
4)指定完标签体后,doAfterBody()方法被调用,该方法返回EVAL_BODY_AGAIN或SKIP_BODY。返回前者表示重复执行标签体,返回后者表示不再执行标签体。要注意,在执行该方法前,标签体已经被执行了一遍。如果想忽略标签体,需要在doStartTag()方法中返回SKIP_BODY。
后三步和实现Tag接口的标签处理器最后三步相同。
BodyTag 接口
javax.servlet.jsp.tagext.BodyTag接口继承自IterationTag接口,它又新增了两个方法和一个用作返回值的常量。实现了该接口的标签处理器的生命周期如下:
前3步和实现了IterationTag接口的标签处理器相同
4)调用setBodyContent()方法设置标签处理器的bodyContent属性,接着调用doInitBody()方法,为标签体执行做准备。
后四步和实现了IterationTag接口的标签处理器最后四步相同。
标签库描述符
编写好标签处理器类以后,为了使用标签,还需要在标签库描述符文件中配置标签的相关信息。标签库描述符(Tag Library Descriptor,TLD)是一个xml文档。标签库描述符文件使用的扩展名是“.tld”。当标签库部署在jar文件中时,标签库描述符文件必须放在META-INF目录或其子目录下。当标签库直接部署在web应用程序中时,标签库描述符文件必须放在WEB-INF目录或其子目录下,但不能放在WEB-INF\classes或WEB-INF\lib目录下。
<taglib>元素是标签库描述符的根元素,它包含13个子元素,具体内容如下:
(1)<description>:标签库的一个文本描述。
(2)<tlib-version>:指定标签库的版本。
(3)<short-name>:为标签定义简短的名字,在taglib指令中可作为首选的前缀名使用。
(4)<uri>:定义一个URI,用于唯一地标识此标签库。
(5)<tag>:用于指定自定义标签的相关信息。
(6)<display-name>:为标签库指定一个简短的别名。
(7)<small-icon>:为标签库指定大小为16×16的小图标(gif或jpeg格式),该图标可在图形界面工具中显示。
(8)<large-icon>:为标签库指定大小为32×32的大图标(gif或jpeg格式),该图标可在图形界面工具中显示。
(9)<validator>:为标签库提供一个验证器。
(10)<listener>:为标签库提供一个监听器。
(11)<tag-file>:用于描述标签文件。
(12)<function>:用于指定在表达式语言中使用的函数。
(13)<taglib-extension>包含一个或多个<extension-element>元素,用于提供标签库的扩展信息。
自定义标签库的内容如上所述。现在我们通过一些实例来加深理解。
新建一个工程TestTag,建立方法如前面所述。
我们定制一个<hello>标签,用于向用户输出欢迎信息。首先编写标签处理器类,代码如下:
package com.shan.tag; import java.io.*; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class HelloTag implements Tag { private PageContext pageContext; private Tag parent; public void setPageContext(PageContext pc) { this.pageContext = pc; } public void setParent(Tag t) { this.parent = t; } public Tag getParent() { return parent; } public int doStartTag() throws JspException { return SKIP_BODY; } public int doEndTag() throws JspException { //利用pageContext对象的getOut()方法得到JspWriter对象 JspWriter out = pageContext.getOut(); try { //利用JspWriter对象,向客户端发送欢迎消息 out.println("Welcome to Tag's world!"); } catch(IOException e) { System.out.println(e.toString()); } return EVAL_PAGE; } public void release() { } }然后在dos环境下切换到工程目录,执行如下语句,编译TestTag.java文件。
javac -classpath D:\apache-tomcat-7.0.33\lib\jsp-api.jar;classes -d classes src\com\shan\tag\HelloTag.java编译完成后,在工程目录下的classes\com\shan\tag文件夹下会生成对应的.class文件。
在tld文件中配置<hello>标签
新建文件MyTaglib.tld文件,内容如下:
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>mytag</short-name> <display-name>MyTag</display-name> <description>My Tag library.</description> <tag> <name>hello</name> <tag-class>com.shan.tag.HelloTag</tag-class> <description> Display JSP sources </description> <body-content>empty</body-content> </tag> </taglib>
编辑web.xml文件。内容如下:
<?xml version='1.0' encoding='utf-8'?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true"> <jsp-config> <taglib> <taglib-uri>/mytag</taglib-uri> <taglib-location>/WEB-INF/MyTaglib.tld</taglib-location> </taglib> </jsp-config> </web-app>
编写一个测试页面test.jsp,内容如下:
<%@ page contentType="text/html;charset=gb2312" %> <%@taglib uri="/mytag" prefix="mytag"%> <html> <head><title><mytag:hello/></title></head> <body><mytag:hello/></body> </html>
在tomcat安装文件夹下的webapps目录下建立TestTag目录,在其中建立WEB-INF文件夹,将刚编译过的classes目录和MyTaglib.tld文件,web.xml文件拷贝到WEB-INF文件夹下,将test.jsp文件拷贝的TestTag目录下。打开tomcat服务器,在网址栏输入localhost:8080\TestTag\test.jsp,运行结果下图所示:
转载请注明出处:http://blog.csdn.net/iAm333