JSP标记学习笔记XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />
ginkou.fly 2002-9-18
1. 概述
1) 什么是JSP标记
顾名思义,JSP标记就是在JSP文件中使用的标记。它类似于html语法中的标记,像head 、table 。通过在JSP文件中引用它(就像使用html标记那样),可以更方便的实现对Java 代码模块的重用。
2) 为什么要使用JSP 标记技术(与javabean相比)
好处:
J JSP 标记可以处理JSP正文的内容,比如改变文本显示样式;而javabean不可以。
J JSP标记接口简单,易于使用,也易于开发和维护。
坏处:
L JSP标记在进行设置时要比javabean复杂很多,体现在JSP标记库描述文件(*.tld)的配置上。
L JSP标记实现的功能远不如javabean强大。
L 当前只要JSP1.1支持JSP标记,而JSP1.0和1.1都支持对Bean的使用。
2. JSP标记的开发简介。
JSP标记的开发需要编写2种独立的文件。一种是定义标记功能的java类文件,一种是将xml元素名称(标记)映射到标记实现的标记库描述符文件。
⑴ 编写标记处理程序类文件
需要继承javax.servlet.jsp.tagext.TagSupport类;
简单示例:
//文件名ExampleTag.java
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
public class ExampleTag extends TagSupport {
//程序的执行起始点
public int doStartTag() {
try {
JspWriter out=pageContext.getOut();
out.print(“Custom tag example”);
}catch (IOException ioe) {
System.out.println(“Error in ExampleTag : “ + ioe);
}
return(SKIP_BODY);
//当标记包括的内容为空时返回SKIP_BODY,表示标记功能
//已执行完成
}
}
编译好的class文件将位于服务器的的特定位置。
⑵ 编写标记库描述符文件
将标记名和其代表的功能实现联系在一起。
简单示例:
<!--文件名:csajsp-taglib.tld-->
xml version=”1.0” encoding=”ISO-8859-1” ?>
PUBLIC “-//Sun Microsystem,Inc.//DTD JSP Tag Library 1.1//EN”
J2EE/dtds/web-jsptaglibrary_1_1.dtd">http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd>
//以上是标准的文件头
//以下是标签库描述
//以下定义新标记
此文件将配置在服务器的特定位置
⑶ 使用以上自定义的标记
<!--文件名:simpleExample.jsp-->
<%@ taglib uri = “csajsp-taglib.tld” prefix = “csajsp” %> //进行标记使用声明
TYPE=”text/css”>
/使用标记
这样最终在在浏览器上输出为
Custom tag example
3. 深入的JSP标记开发
⑴ 添加标记属性
在标记处理类中可以通过函数setAttribute(String value) 为jsp标记分配属性,这样标记处理程序根据获取的属性值来实现相关功能。
比如 private String message = “Default Message”;
public void setMessage(String message) {
this.message=message;
}
注意:属性名message是小写的,设置函数中的Message是大写的。
◆与之相关的在tld文件中需要在tag元素中添加如下元素
//ture表示属性值可以使用jsp表达式,false表示禁
//止使用
◆对应jsp文件中引用为:
⑵ 使用标记正文
即是在标记中使用一些包含jsp脚本元素、文本等的内容,这些内容由jsp引擎处理。
形式如下:
在处理jsp标记的正文前,将会调用处理程序的doStartTag()方法,此时要在此方法中返回EVAL_BODY_INCLUDE 以表明包含有标记正文;处理完后,将会调用doEndTag()方法,此后要让jsp引擎继续处理后面的页面,得返回EVAL_PAGE,否则返回SKIP_PAGE。
◆对应在tld文件中需要在tag元素中添加如下元素
…
…
另外:可以设置一些条件来判断是否包含正文的,如下:
public int doStartTag() {
ServletRequest request = pageContext.getRequest();
String debugFlag = request .getParameter(“debug”);
If ((debugFlag!=null) && (!debugFlag.equalsIgnoreCase(“false”))) {
Return (EVAL_BODY_INCLUDE);
}
else {
return(SKIP_BODY);
}
}
这样只有在url尾部给出请求参数值debug = true,才会显示标记正文的内容。这样可以隐藏一些调试信息。
⑶ 对标记正文进行处理
jsp的标记可以对包含的正文进行处理(修改),然后再输出。这需要标记处理类继承BodyTagSupport类(TagSupport类的继承)。这个类提供了2个重要的方法用于正文处理。
→ doAfterBody:默认执行的方法,在此方法中包含正文的处理过程。
→ getBodyContent:返回BodyContent类型的的对象,此对象包含了有关标记正文的信息。
BodyContent类型包含的重要方法:
→ getEnclosingWriter:返回JspWriter方法,输出内容。
→ getString:返回包含全部jsp标记正文的字符串。
注意:这里和⑵中介绍的输出jsp标记正文的方式不一样。前者的输出是先由jsp引擎解释,这里是在jsp标记处理程序中直接输出到给浏览器。
另外,在doAferBody中返回SKIP_BODY,表示终止标记正文处理;若返回的是EVAL_BODY_TAG,将会再一次调用doAferBody方法,重新处理标记正文,直到返回SKIP_BODY为止。
示例:
→标记处理程序片:
//下面的程序片将调用一个filter方法,此方法用于把jsp正文中的字符< > “ & 分别用⁢ > &guot; &来代替。以使浏览器按字符原样输出,不进行解释。
public class FillterTag extends BodyTagSupport {
public int doAfterBody() {
BodyContent body=getBodyContent();
String filteredbody=ServletUtilities.filter(body.getString()); //将正文得到的字符串过滤
Try {
JspWriter out=body.getEnclosingWriter();
out.print(filteredBody); //输出过滤后的文本
}catch(IOException ioe) {
System.out.println(“Error in FilterTag: “ + ioe);
}
return(SKIP_BODY); //终止jsp正文处理
}
→标记符描述文件片
…
…
→jsp文件片
I love you!
I love you!
这样,在浏览器中输出的标记正文应当是
I love you!
I love you!
而不是
I love you!
I love you!
⑶使用jsp嵌套标记。
可以对多个JSP标记进行嵌套引用,这样子标记就可以访问和存储父标记的数据和方法。
子标记访问父标记需要使用BodyTagSupport类中的 findAccetorWithClass方法。注意它只能查找临近的父标记。
假如在jsp文件中如下的嵌套引用:
相应的标记处理程序片:
→对于if标记,执行类如下:
public class IfTag extends TagSupport {
private boolean condition ;
private Boolean haSCOndition = flase ;
public void setCondition(Boolean condition) { //设置判断条件的真假;condition子标
//记调用
this.condition = condition ;
hasCondition = true ;
}
public Boolean getCondition() { //获取判断条件的真假then 、else子标
//记调用
return(condition) ;
}
public void setHasCondition(Boolean flag) { //判断if标记后是否存在条件,由
//condition子标记调用
this.hasCondition = flag ;
}
public Boolean getHasCondition() { //获取是否存在判断条件的信息,由
//then、else标记调用
return(hasCondition) ;
}
public int doStartTag() {
return(EVAL_BODY_INCLUDE) //包含子标记
}
}
→那么对于condition等其它子标记的处理程序,需要获取父标记处理程序对象:
IfTag parent=(IfTag) findAncestorWithClass(this,IfTag.class)
之后就可以操作父标记处理程序的相应方法。
示例:(对于condition标记)
public class IfConditionTag extends BodyTagSupport {
ifTag parent = (IfTag)findAncestorWithClass(this,IfTag.class); //获取父标记对应的对象
If (parent = = null) {
Throw new JspTagException(“condition not inside it”);
}
return(EVAL_BODY_TAG);
}
public int doAfterBody() {
ifTag parent = (IfTag) findAncestorWithClass(this , IfTag.class) ;
String bodyString = getBodyContent() . getString() ;
If (bodyString.trim().equals(“true”)) {
Parent.setCondition(true) //访问父标记处理类中的方法
}else {
parent.setCondition(false) ;
}
return(SKIP_BODY) ;
}
}
其余标记类和此相似。
4. 小结
对于一些不太复杂和功能单一的逻辑描述,需要传递的参数要求不高时,使用JSP标记,要方便的多。对于大多数的商业逻辑应用,还是使用bean要好的多,也宜于servlet控制。
这个东东是俺学习 人邮 出的Servletlet与JSP核心技术》时随手写下的。里面的程序还没具体配置过。过段时间弄了再搞篇实验体会吧。
有什么值的商讨的发eMail哦。ginkou@163.com