是一个标签库中的某个标签,其中Jsp为该标签库的库名,forward为标签名称。
在JSP中,一个标签看起来很象一个标准的HTML标签。但是,它的逻辑不在客户端被执行,而是由服务器端的Servlet来转换。每个标签被封装到一个独立的类,它的名字和参数属性被一个特殊的.tld扩展名的部署描叙文件中来指出。
通过使用标签库技术也能使网页设计师不用编程JSP的Java代码就操作复杂的数据库和事务等。特别适用于需要重复使用某一段程序的地方。
5、定制标签的编程实现步骤:
l JavaBean:为了充分利用Java的面向对象特性,重用代码应当放置在独立的代码容器内。这些JavaBean可不是标签库的一部分。它们是标签库用来执行所分配任务的基础代码模块(可以将这些*.class文件发布为JAR文件)。
l 标签库描述符(TLD文件):这是一种很简单的XML文件,TLD文件描述和说明了属性、信息和标签处理器文件位置等信息。JSP 容器使用这一文件来映射被调用标签库的位置和用法。
l Web站点的web.xml文件:其实这就是你的Web站点上的初始化文件。在这个文件内你可以定义Web应用程序中使用的定制标签,还可以定义用来描述每个定制标签的TLD文件。
l JSP页面上的标签库声明:仅需使用标签库标示符即可方便地声明页面上存在的标签。标签库在页面上声明之后,你就可以随意使用它们了。
6、不带属性和标签体的简单标签的开发例
JSP标签的开发需要编写两种独立的文件。一种是定义标签功能的java类文件,一种是将xml元素名称(标签)映射到标签实现的标签库描述符文件。
(1)编写标签处理程序的JAVA类文件( TAG处理器)
当一个JSP引擎遇到一个定制的标签时,它首先检查是否能够确定这个标签类的物理位置。如果能够确定,就会执行标签类中对应的代码。
该标签类的Java文件执行由标签所标示的具体工作,并应该被放置在WEB-INF下的classes目录或者其下的某一子目录(取决于是否有包的定义)下。标签类通常页可以被制作成一个JAR文件,放置在WEB-INF目录下的lib目录中。
需要在tld标签库描述文件里的每个TAG标签中指明是应用哪一个类文件来对这个TAG进行处理。
/*
在JCreator中编译该程序时要注意:由于在JDK.14中
并没有包含javax.servlet.jsp.*、javax.servlet.jsp.tagext.*等包,
应该在JCreator中引入这些包,这些包可以从
Tomcat\common\lib\jsp-api.jar和servlet-api.jar文件
*/
package jspTagLib;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
public class JSPTagTest extends TagSupport
{
public int doStartTag() //程序的执行起始点
{
try
{
/*
out是一个JspWriter类型的隐含对象,
用于向jsp网页输出内容。输出的目标由pageContext.getout提供 ,
其中pageContext是TagSupport类中的一个PageContext类的对象
*/
JspWriter out=pageContext.getOut();
//向jsp网页上下文输出
out.println("这是定制JSP标签所输出的文字"); }
catch(Exception e)
{
System.out.println("tag err!");
}
//由于没有标签体,因此返回SKIP_BODY,表示标签功能已执行完成
return(this.SKIP_BODY);
}
}
编程要点:
(1)需要继承javax.servlet.jsp.tagext.TagSupport类并重写doStartTag方法。JSP服务器引擎当它第一次遇到这个标记的时候,引擎就会调用doStartTag ()方法。
l 可以使这个方法为空或者当需要的时候才执行应用程序逻辑。
l 当该方法返回SKIP_BODY时,那么引擎跳过这个标记体。
l 当它返回EVAL_BODY_INCLUDE时,引擎将会处理这个标记以及它的子标记。
(2)在JCreator中编译该程序时要注意:由于在JDK.14中并没有包含javax.servlet.jsp.*、javax.servlet.jsp.tagext.*等包,应该在JCreator中引入这些包,这些包可以从Tomcat\common\lib\jsp-api.jar和servlet-api.jar文件获得
(3)将编译好的class文件放于服务器的WEB-INF下的classes目录下(由于该Java程序有包的定义,因此应该将它的*.class文件放在WEB-INF\classes\jspTagLib目录下,其中jspTagLib为包名)。
注意:
l 只需要将该JSPTagTest.java文件放在WEB-INF\classes目录下,然后对它进行编译将自动会形成上述目录位置。
l 也可以将标签类的文件制作成一个JAR文件,放置在WEB-INF目录下的lib目录中。
(4)编写标签库描述符TLD文件(Tag Library Descriptor,文件扩展名为*.tld)
通过该文件实现将标签名和其代表的功能实现联系在一起,它规定了标签和Java程序类的映射关系,由容器解释;它是标准的XML格式的标记定义文件,可以定义标签和它的各种属性(包括它的名称,版本和其它的任选信息)和处理文件等等;
文件名:目录WEB-INF/taglib
JSPTageTest.tld
"">
1.0
1.1
userTag
标签库的使用描述信息
处理这个标签的java类的名字可以(包含有包的名称),不同的标签可能对应不同的java类来处理 |
JSPTagTest
jspTagLib.JSPTagTest
标签的描述信息
注意:只有黑体的两句最重要,其他就照抄;该文件需要放置在WEB-INF目录或其子目录下。
对WebLogic也是一样的要求
(5)修改WEB-INF目录下的web.xml文件以定位标签的*.tld文件
在web-app之间添加如下的项目:
/taglib/JSPTagTest.tld
/WEB-INF/taglib/JSPTagTest.tld
自定义的标签库名的前缀,请不要用jsp, jspx, java, javax, servlet, sun, 和sunw做为你的前缀 |
进行标记使用声明,声明此JSP文件使用了自定义的标签,同时引用标签库,也指定了他们的标签的前缀。 |
(6)在JSP页面中使用以上自定义的标记
<%@ taglib uri="/taglib/JSPTagTest.tld" prefix="userTag" %>
应该与前面*.tld文件中的name声明的标签名保持相同 |
7、标签转换机制
首先调用JSP引擎把JSP页面翻译成一个servlet,然后再编译servlet。 与标记库相关联的方法都被包含在servlet中。
8、为什么要使用JSP 标签技术(与JavaBean相比)
JSP 1.1提出了一种扩展的JSP标签的方法,这种方法命名为“标签库”。JSP标签从本质上代表着一个JSP功能的调用,即一个标签触发一次函数调用。同时标签也具有JavaBean所具有的业务逻辑处理能力。
(1)优点:
JSP 标签可以处理JSP正文的内容,比如改变文本显示样式,而JavaBean不可以;
JSP标签接口简单,易于使用,也易于开发和维护。
(2)缺点:
JSP标签在进行设置时要比JavaBean复杂很多,体现在JSP标签库描述文件(*.tld)的配置上;
JSP标签实现远不如JavaBean方便。
9、标签的类型
(1)不带属性和标签体的简单标签
(2)不带标签体但有属性的标签
(3)带标签体同时也有属性的标签
此内容为该标签的标签体
10、TagSupport和BodyTagSupport类
在编程定义标签功能的java类文件时,可以采用实现Tag接口或者继承TagSupport类的方法,但一般都采用继承TagSupport类的方法。
但对带标签体的标签,在编程定义该类型的标签功能的java类文件时,可以采用实现BodyTag接口或者继承BodyTagSupport类的方法,但一般都采用继承BodyTagSupport类的方法。
两者的主要区别是标签处理类是否需要与标签体交互(也即标签处理类是否要读取标签体的内容和改变标签体返回的内容),如果不需要交互的应用就用TagSupport,否则就用BodyTagSupport。
二、带属性的JSP标签的开发例
(1)编程要点
一个标签能接受输入参数,只需要在该标签所对应的Java类程序中增加setXXX()方法即可,其中xxx为该标签的属性名称 。
(2)编写带属性的标签处理程序的JAVA类文件
package jspTagLib;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
public class JSPTagTest extends TagSupport
{
private String tagproperty="属性的缺省值"; // tagproperty为该标签的属性名称
public int doStartTag() //程序的执行起始点
{
try
{
/*
out是一个JspWriter类型的对象,用于向jsp网页输出内容。输出的目标由pageContext.getOut提供 ,其中pageContext是TagSupport类中的一个PageContext类的对象
*/
JspWriter out=pageContext.getOut();
if(tagproperty.equals("属性的缺省值"))
{
out.println("这是定制JSP标签所输出的文字并且没有设置属性");
}
else
{
out.println("这是定制带属性的JSP标签所输出的文字,您所设置的tagproperty属性的值为:"+tagproperty);
}
//向jsp网页上下文输出,在JspWriter类中的println()方法与PrintWriter类中的println()不同,它有IOException异常声明
}
catch(IOException e)
{
System.out.println(e.getMessage());
}
return this.SKIP_BODY; //当标签包括的内容为空时返回SKIP_BODY,表示标签功能已执行完成
}
/*
重写doEndTag()方法后,该标签可以以如下两种方式来使用(否则只能以方式来使用)
或者
*/
public int doEndTag() throws JspException
{
return(EVAL_PAGE);
}
public void setTagproperty(String newTagproperty)
{
this.tagproperty=newTagproperty;
}
}
(3)修改标签库描述符TLD文件(仍然采用前面示例中的TLD文件)
"">
1.0
1.1
userTag
标签库的使用描述信息
JSPTagTest
jspTagLib.JSPTagTest
定义属性的名称,必须与*.java中的String tagproperty保持相同 |
标签的描述信息
empty
说明该属性是否必须出现在标记中,此属性为可选的并且有缺省值 |
tagproperty
false
true
说明是否该属性可以采用<%=expression%>JSP表达式来赋值
//止使用
使用 |
(4)对WEB-INF目录下的web.xml文件仍然采用前面例中的web.xml文件
(5)在JSP页面中使用该标签
<%@ taglib uri="/taglib/JSPTagTest.tld" prefix="userTag" %>
"<%=request.getParameter(\"formItemName\")%>"> />
三、设计采用成对的标签例(如:这是成对的标签正文内容)
(1)编程要点
l 此时应该在标记Java程序类中同时重载doStartTag()和doEndTag()方法,上面的两个标签分别调用这两个方法。
l 而如果要求将“这是成对的标签正文内容”字符串原样输出,则应该注意的是在doStartTag()中需要返回return(EVAL_BODY_INCLUDE)表示要求计算标签体正文内容,而不是return(SKIP_BODY)表示跳过标签体正文内容
l 而doEndTag()需要return(EVAL_PAGE)表示要求容器在标签结束时继续计算JSP页面其他的部分。
(2)编写带属性的标签处理程序的JAVA类文件
/*
在JCreator中编译该程序时要注意:由于在JDK.14中并没有包含javax.servlet.jsp.*、javax.servlet.jsp.tagext.*等包,应该在JCreator中引入这些包,这些包可以从Tomcat\common\lib\jsp-api.jar和servlet-api.jar文件
*/
package jspTagLib;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
public class JSPTagTest extends TagSupport
{
private String tagproperty="属性的缺省值";
public int doStartTag() //程序的执行起始点
{
try
{
/*
out是一个JspWriter类型的隐含对象,用于向jsp网页输出内容。输出的目标由pageContext.getOut提供 ,其中pageContext是TagSupport类中的一个PageContext类的对象
*/
JspWriter out=pageContext.getOut();
if(tagproperty.equals("属性的缺省值"))
{
out.println("这是定制JSP标签所输出的文字并且没有设置属性");
}
else
{
out.println("这是定制带属性的JSP标签所输出的文字,您所设置的tagproperty属性的值为:"+tagproperty);
}
//向jsp网页上下文输出,在JspWriter类中的println()方法与PrintWriter类中的println()不同,它有IOException异常声明
}
catch(IOException e)
{
System.out.println(e.getMessage());
}
return this.EVAL_BODY_INCLUDE; //当标签包括有标签体内容时不能再返回SKIP_BODY
}
public int doEndTag() throws JspException //结束标签
{
return(EVAL_PAGE);
}
public void setTagproperty(String newTagproperty)
{
this.tagproperty=newTagproperty;
}
}
注意:JSP引擎在分析了结束标记之后就会调用doEndTag ()方法。
(3)修改*.tld文件(仍然采用前面示例中的TLD文件),所应该注意的是要在标签之间加“JSP”标签,表示标签有标签体内容
JSPTagTest
jspTagLib.JSPTagTest
标签的描述信息
JSP
tagproperty
false
true
(4)对WEB-INF目录下的web.xml文件仍然采用前面例中的web.xml文件
(5)在JSP页面中使用该标签
<%@ taglib uri="/taglib/JSPTagTest.tld" prefix="userTag" %>
这是成对的标签正文内容
四、如果需要处理标签对间的信息---带标签体的标签并且对标签体进行处理例
(1)编程要点:从继承BodyTagSupport类,并重载doAfterBody()方法。
(2)编写该类型的标签处理程序的JAVA类文件,可以将标签类继承BodyTagSupport类,并重载doAfterBody()方法。
/*
在JCreator中编译该程序时要注意:由于在JDK.14中并没有包含javax.servlet.jsp.*、javax.servlet.jsp.tagext.*等包,应该在JCreator中引入这些包,这些包可以从Tomcat\common\lib\jsp-api.jar和servlet-api.jar文件
*/
package jspTagLib;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
/*
继承BodyTagSupport类的主要目的是能够处理标签的正文内容,否则应该继承TagSupport类
*/
public class JSPTagTest extends BodyTagSupport
{
private String tagproperty="属性的缺省值";
public int doStartTag() //程序的执行起始点
{
try
{
/*
out是一个JspWriter类型的隐含对象,用于向jsp网页输出内容。输出的目标由pagecontext.getout提供 ,其中pageContext是TagSupport类中的一个PageContext类的对象
*/
JspWriter out=pageContext.getOut();
if(tagproperty.equals("属性的缺省值"))
{
out.println("这是定制JSP标签所输出的文字并且没有设置属性");
}
else
{
out.println("这是定制带属性的JSP标签所输出的文字,您所设置的tagproperty属性的值为:"+tagproperty);
}
//向jsp网页上下文输出,在JspWriter类中的println()方法与PrintWriter类中的println()不同,它有IOException异常声明
}
catch(IOException e)
{
System.out.println(e.getMessage());
}
return this.EVAL_BODY_INCLUDE;
//当标签包括有标签体的内容时不能再返回SKIP_BODY, 表示要求计算标签体正文内容
}
/*
该方法主要是为了能够处理结束标签的
*/
public int doEndTag() throws JspException
{
return(EVAL_PAGE); //表示要求容器在标签结束时继续计算JSP页面其他的部分
}
/*
该方法主要是为了给标签提供属性项目的
*/
public void setTagproperty(String newTagproperty)
{
this.tagproperty=newTagproperty;
}
/*
该方法主要是为了处理标签之间的标签体正文内容的,该方法是默认执行的方法,在此方法中包含对正文的处理过程与逻辑
*/
public int doAfterBody()
{
BodyContent tagContentText=getBodyContent(); //获得标签之间的正文内容
String contentString=tagContentText.getString(); //返回包含jsp标签正文的全部字符串
try
{
JspWriter out=pageContext.getOut();
out.println(contentString); //将标签之间的正文内容在页面中输出
}
catch(Exception e)
{
}
// 在doAferBody中返回SKIP_BODY,表示终止标签体正文处理;若返回的是EVAL_BODY_TAG,将会再一次调用doAferBody方法,重新处理标记正文,直到返回SKIP_BODY为止。
return this.SKIP_BODY;
}
}
(3)注意:doAfterBody ()方法是在JSP引擎处理标签体正文之后被执行,它在doEndTag ()方法之前被调用。
五、访问数据库的标签设计例
(1)标签处理程序,请见GetDBDataTag.java文件。在该程序中实现数据库的连接和操作并将所操作的结果直接输出到页面上,实现某一独立的功能。
package jspTagLib;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.sql.*;
public class GetDBDataTag extends TagSupport
{
Connection con = null;
Statement state = null;
ResultSet rs = null;
String url="jdbc:odbc:WebMisDB";
String DBDriver="sun.jdbc.odbc.JdbcOdbcDriver";
public GetDBDataTag()throws ClassNotFoundException
{
Class.forName(DBDriver);
}
public int doStartTag() throws JspTagException
{
return EVAL_BODY_INCLUDE;
}
public int doEndTag()throws JspTagException
{
try
{
JspWriter out = pageContext.getOut();
con=DriverManager.getConnection(url,"yanguser","1234");
String strQuery = "select id,bookName,publisher,bookAuthor,price,time from BookInfo where id >=100";
state = con.createStatement();
rs = state.executeQuery(strQuery);
int bookID;
String bookName=null;
String bookPublisher=null;
String bookAuthor=null;
int bookPrice;
String publisherTime;
out.write("") ;
out.write("");
out.write("
");
while(rs.next())
{
bookID = rs.getInt("id");
bookName = rs.getString("bookName");
bookPublisher = rs.getString("publisher");
bookAuthor = rs.getString("bookAuthor");
bookPrice = rs.getInt("price");
publisherTime=rs.getString("time");
out.write("");
out.write("
"+bookID+" | ");
out.write("
"+bookName+" | ");
out.write("
"+bookAuthor+" | "); out.write(""+bookPublisher+" | ");
out.write("
"+bookPrice+" | ");
out.write("
"+publisherTime+" | "); out.write("
");
}
out.write("
");
}
catch(Exception e)
{
throw new JspTagException("不能正确地连接数据库!");
}
return EVAL_PAGE;
}
}
(2)编写TLD文件,请见GetDBDataTag.tld文件
"">
1.0
1.1
getDBTag
标签库的使用描述信息
GetDBDataTag
jspTagLib.GetDBDataTag
标签的描述信息
JSP
(3)在部署web.xml文件中添加如下的信息
/taglib/GetDBDataTag.tld
/WEB-INF/taglib/GetDBDataTag.tld
(4)在JSP页面中使用该标签
<%@ page contentType="text/html;charset=gb2312" errorPage="DealError.jsp"%>
<%@ taglib uri="/taglib/GetDBDataTag.tld" prefix="getDBTag" %>
….
六、访问数据库的带属性的标签设计例
(1)标签处理程序,请见GetDBDataWithAttrTag.java文件。
在该程序中实现数据库的连接,并从标签所带的属性中获得属性的值。该值将作为数据库表的操作条件,然后将操作的结果直接输出到页面上,实现某一独立的功能。
package jspTagLib;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.sql.*;
public class GetDBDataWithAttrTag extends TagSupport
{
Connection con = null;
PreparedStatement pstate = null;
ResultSet rs = null;
String url="jdbc:odbc:WebMisDB";
String DBDriver="sun.jdbc.odbc.JdbcOdbcDriver";
private int minID;
private int maxID;
/*
下面是属性的get和set方法.注意其方法的命名规则
*/
public void setMinID(String newMinID)
{
this.minID = Integer.parseInt(newMinID);
}
public String getMinID()
{
return new Integer(this.minID).toString();
}
public void setMaxID(String newMaxID)
{
this.maxID = Integer.parseInt(newMaxID);
}
public String getMaxID()
{
return new Integer(this.maxID).toString();
}
public GetDBDataWithAttrTag()throws ClassNotFoundException
{
Class.forName(DBDriver);
}
public int doStartTag() throws JspTagException
{
return EVAL_BODY_INCLUDE;
}
public int doEndTag()throws JspTagException
{
/*
out是一个JspWriter类型的对象,用于向jsp网页输出内容。输出的目标由pageContext.getOut提供 ,
其中pageContext是TagSupport类中的一个PageContext类的对象
*/
try
{
JspWriter out = pageContext.getOut();
con=DriverManager.getConnection(url,"yanguser","1234");
String strQuery = "select id,bookName,publisher,bookAuthor,price,time from BookInfo where id >= ? and id<= ?";
pstate = con.prepareStatement(strQuery,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
pstate.setInt(1,minID);
pstate.setInt(2,maxID);
rs = pstate.executeQuery();
int bookID;
String bookName=null;
String bookPublisher=null;
String bookAuthor=null;
int bookPrice;
String publisherTime;
out.write("") ;
out.write("");
out.write("
");
while(rs.next())
{
bookID = rs.getInt("id");
bookName = rs.getString("bookName");
bookPublisher = rs.getString("publisher");
bookAuthor = rs.getString("bookAuthor");
bookPrice = rs.getInt("price");
publisherTime=rs.getString("time");
out.write("");
out.write("
"+bookID+" | ");
out.write("
"+bookName+" | ");
out.write("
"+bookAuthor+" | ");
out.write("
"+bookPublisher+" | ");
out.write("
"+bookPrice+" | ");
out.write("
"+publisherTime+" | "); out.write("
");
}
out.write("
");
}
catch(Exception e)
{
throw new JspTagException("不能正确地连接数据库!");
}
return EVAL_PAGE;
}
}
(2)TLD文件,请见GetDBDataWithAttrTag.tld文件
"">
1.0
1.1
getDBWithAttrTag
标签库的使用描述信息
GetDBDataWithAttrTag
jspTagLib.GetDBDataWithAttrTag
标签的描述信息
JSP
minID
true
true
maxID
true
true
(3)TOMCAT部署web.xml文件
/taglib/GetDBDataWithAttrTag.tld
/WEB-INF/taglib/GetDBDataWithAttrTag.tld
(4)在JSP页面中使用该标签
<%@ page contentType="text/html;charset=gb2312" errorPage="DealError.jsp"%>
<%@ taglib uri="/taglib/GetDBDataWithAttrTag.tld" prefix="getDBWithAttrTag" %>
….
阅读(480) | 评论(0) | 转发(0) |