JSP标签编程 1
标签编程在实际开发之中,并不是很常见,就是说自己开发标签的情况基本上是不存在的,因为这个与开发的环境所限制,因为自己开发之后的标签基本上没有任何的通用性,所以在实际中基本上都是大量的使用已经开发好的标签,例如:之后讲解的JSTL或者是Struts 中都有标签
之所以在这类讲解标签的开发,注意目的是帮助大家建立一个完整的知识体系
本程序中的Scriptlet代码实在是太多了,肯定不方便修改及维护,但是很多时候一个jsp 页面又不能去避免的要使用的Scriptlet代码,因为JSP 需要输出,那么此时的之中矛盾就可以通过标签来完成。
定义一个简单的标签 ----- 空标签
要想实现一个标签,可以直接继承javax.servlet.jsp.tagext.TagSupport 类,如果要定义的标签内没有标签体,则直接覆写TagSupport类中的doStartTag() 方法即可
定义标签支持类: HelloTag.java
之前在开发Servlet的时候曾经配置过了一个Servlet 的开发包,但是现在的标签的支持类并不在servlet包之中。将tomcat lib目录下的jsp-api.jar拷贝进行配置
package com.demo;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
public class HelloTag extends TagSupport {
@Override
public int doStartTag() throws JspException {
JspWriter out = super.pageContext.getOut();
try {
out.println("<h1>HelloWorld!!</h1>");
} catch (Exception e) {
// TODO: handle exception
}
return TagSupport.SKIP_BODY; //不在执行标签
}
}
但是,只靠一个标签的支持类本身是无法完成全部功能的
下面还需要定义一个标签的描述文件,标签的描述文件的后缀“*.tld” ,而且此操作依然富豪xml
<?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">
</taglib>
<%@ taglib prefix="mytag" uri="/WEB-INF/hellotag.tld"%> 表示引入标签库
javax.servlet.ServletException: java.lang.NoClassDefFoundError: javax/el/ELResolver
这个项目还有另一种情况 我编译的时候是把 jsp-api.jar C:\jdk6.0\jre\lib\ext 删除后重新启动tomcat 但是java 类在生成classes的时候需要这个类 这是我用editplus 运行后的情况
以下是自定义开发的标签
package com.demo;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
public class HelloTag extends TagSupport {
@Override
public int doStartTag() throws JspException {
JspWriter out = super.pageContext.getOut();
try {
out.println("<h1>HelloWorld!!</h1>");
} catch (Exception e) {
// TODO: handle exception
}
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_1.xsd"
version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>firsttag</short-name>
<tag>
<name>hello</name>
<tag-class>com.demo.HelloTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
<%@ page contentType="text/html; charset=GBK" %>
<%@ taglib prefix="mytag" uri="/WEB-INF/hellotag.tld"%>
<html>
<head>
<title>欢迎光临</title>
</head>
<body>
<h1><mytag:hello/></h1> <!-- 访问标签 -->
</body>
</html>
此时,已经完成了输出功能,但是这些功能是直接由标签的支持类所完成的,而只有通过tld文件才可以使用这个标签的支持类,当然,在标签的开发中也可以将所有的标签库的描述文件直接在web.xml 文件之中进行配置
是在web.xml 文件组之中为tld 的文件走了一个映射,映射的名称就是myhello 。以后在JSP 页面中,就可以直接通过myhello进行访问了<jsp-config> <taglib> <taglib-uri>myhello</taglib-uri> <taglib-location>/WEB-INF/hellotag.tld</taglib-location> </taglib> </jsp-config>
<%@ page contentType="text/html; charset=GBK" %> <%@ taglib prefix="mytag" uri="myhello"%> <html> <head> <title>欢迎光临</title> </head> <body> <h1><mytag:hello/></h1> <!-- 访问标签 --> </body> </html>
标签操作之中文件配置的非常多,需要标签的支持类,标签的描述文件,如果需要还可以在web.xml 文件之中配置,还需要在jsp中进行引入
本身非常麻烦
因为之前一直强调过, 在一个JSP文件之中,基本功能:判断、输出
小结:
标签可以简化JSP中的Scriptlet,但是从实际开发来讲,自定义标签库使用并不多
标签需要*.tld文件的支持,之后使用<%@taglib%>
————————————————————————————————————————————————————
本章目标
JSP标签编程
定义有属性的标签
本章目标
理解标签中熟悉的设置方法
理解标签配置文件中的属性定义格式
上面已经清楚的知道了,对于一个标签的开发需要标签的支持了,标签库的描述文件、web.xml文件中进行配置、之后在JSP中进行使用
但是对于属性:<jsp:forward page=""/>, 现在自己的标签也可以定义属性操作
下面定义一个可以完成日期格式化显示的操作,希望用户可以输入自己的日期的格式化的模板,根据此模板最终完成标签
是在web.xml 文件组之中为tld 的文件走了一个映射,映射的名称就是myhello 。以后在JSP 页面中,就可以直接通过myhello进行访问了<jsp-config> <taglib> <taglib-uri>myhello</taglib-uri> <taglib-location>/WEB-INF/hellotag.tld</taglib-location> </taglib> </jsp-config>
<%@ page contentType="text/html; charset=GBK" %> <%@ taglib prefix="mytag" uri="myhello"%> <html> <head> <title>欢迎光临</title> </head> <body> <h1><mytag:hello/></h1> <!-- 访问标签 --> </body> </html>
标签操作之中文件配置的非常多,需要标签的支持类,标签的描述文件,如果需要还可以在web.xml 文件之中配置,还需要在jsp中进行引入
本身非常麻烦
因为之前一直强调过, 在一个JSP文件之中,基本功能:判断、输出
小结:
标签可以简化JSP中的Scriptlet,但是从实际开发来讲,自定义标签库使用并不多
标签需要*.tld文件的支持,之后使用<%@taglib%>
———————————————————————————————————————————————————
本章目标JSP标签编程
定义有属性的标签
理解标签中熟悉的设置方法
理解标签配置文件中的属性定义格式
上面已经清楚的知道了,对于一个标签的开发需要标签的支持了,标签库的描述文件、web.xml
文件中进行配置、之后在JSP中进行使用
但是对于属性:<jsp:forward page=""/>, 现在自己的标签也可以定义属性操作
下面定义一个可以完成日期格式化显示的操作,希望用户可以输入自己的日期的格式化的模板
,根据此模板最终完成标签
此处的format 就是一个标签操作中所需要的属性,而此属性操作时,必须要有相应的setter、getter方法进行接收package com.demo.tag; import java.text.*; import java.util.*; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; //处理日常日期格式化标签 public class DateTag extends TagSupport { private String format; //标签的格式化操作 public int doStartTag() throws JspException { SimpleDateFormat sdf = new SimpleDateFormat(this.format); //表示日期显示操作 try { super.pageContext.getOut().write(sdf.format(new Date())); } catch (Exception e) { e.printStackTrace(); } return TagSupport.SKIP_BODY; } public void setFormat(String format) { this.format = format; } public String getFormat() { return this.format; } } // 此时完成了标签的处理类操作,之后就需要缩写*.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_1.xsd" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>firsttag</short-name> <tag> <name>date</name> <tag-class>com.demo.tag.DateTag</tag-class> <body-content>empty</body-content> <attribute> <name>format</name> <!-- 属性名通过反射机制 --> <required>true</required> <!-- 此属性必须设置 --> <rtexprvale>true</rtexprvale> <!-- 支持表达式输出 --> </attribute> </tag> </taglib> 下面为了方便的使用,直接在web.xml 文件之中定义此标签库 taglib> <taglib-uri>date</taglib-uri> <taglib-location>/WEB-INF/datetag.tld</taglib-location> </taglib> 下面开始在一个JSP 文件之中使用此标签操作 <?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_1.xsd" version="2.1"> <tlib-version>1.0</tlib-version> <short-name>firsttag</short-name> <tag> <name>date</name> <tag-class>com.demo.tag.DateTag</tag-class> <body-content>empty</body-content> <attribute> <name>format</name> <required>true</required> <rtexprvale>true</rtexprvale> </attribute> </tag> </taglib>
小结
标签中设置的属性依然使用反射机制调用setter方法完成
所以设置的属性要通过TLD文件进行定义
第十二章 JSP 标签编程 ———TagSupport 类
本章目标
掌握TagSupport类的作用
掌握TagSupport类的主要属性及方法
可以定义有标签体的标签
TagSupport 类
基本的标签掌握后,可以发现标签的实现都需要继承TagSupport这个类,所以TagSupport类是整个标签编程的一个核心类,此类的定义如下:
public class TagSupport extends Object implements IterationTag, Serializable
doStartTag()
此方法在标签开始的时候执行,此方法有两种返回值,分别是:
SKIP_BODY: 表示忽略标签体的内容,而将执行权转交给doEndTag() 方法
EVAL_BODY_INCLUDE: 表示执行标签体的内容
doAfterBody()
此方法是IterationTag接口与Tag接口的差别所在,本方法用来重复执行标签体的内容,有两种返回值,分别是:
SKIP_BODY: 表示标签体内容会被忽略,并且执行权转交给doEndTag() 方法
EVAL_BODY_AGAIN: 表示重复执行标签体的内容,会重复调用doAfterBody() 方法,一直循环执行下去,直到doAfterBody() 方法返回SKIP_BODY为止
doEndTag()
在标签结束时执行,此方法有两种返回值
SKIP_PAGE: 表示JSP页面应该立刻停止执行,并将所有的输出立刻回传到浏览器上;
EVAL_PAGE: 表示JSP可以正常的运行完毕
release()
将标签处理类所产生或是活得的资源全部释放,并等待用户下次继续使用
首先标签定义完成之后将执行的doStartTag() 方法,之后判断此方法的返回值,如果是EVAL_BODY_INCLUDE 则表示要执行标签体(doAfterTag()) 如果返回的SKIP_BODY, 表示标签准备结束了
本程序的主要功能是完成一个判断的操作,判断在某一个属性范围之中,是否存在指定的属性名称,如果存在则进行输出
这个过程肯定要使用标签体的。
package com.demo; import java.io.*; import javax.servlet.*; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.*; public class AttributeTag extends TagSupport{ private String name; //接收属性的名称 private String scope; //接收属性的范围 @Override public int doStartTag() throws JspException { //判断属性是否存在 Object value = null; if("page".equals(this.scope)) { value = super.pageContext.getAttribute(this.name,PageContext.PAGE_SCOPE); } if("request".equals(this.scope)) { value = super.pageContext.getAttribute(this.name,PageContext.REQUEST_SCOPE); } if("session".equals(this.scope)) { value = super.pageContext.getAttribute(this.name,PageContext.SESSION_SCOPE); } if("application".equals(this.scope)) { value = super.pageContext.getAttribute(this.name,PageContext.APPLICATION_SCOPE); } if(value == null) { //表示现在根本没有此属性 return TagSupport.SKIP_BODY; //没有属性不执行标签体 } else { return TagSupport.EVAL_BODY_INCLUDE; // 执行标签体 } } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } }
编辑完成之后下面依然需要定义一个*.tld的文件,用于标签库的描述操作现在的由于所有的标签都是由用户自己定义的,为了避免麻烦,以后在讲解的所有标签的开发中,所有的标签的定义操作,都直接在gztag.tld文件中描述了
<?xml version="1.0" encoding="ISO-8859-1"?> <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_2_5.xsd" version="2.5"> <description> Servlet and JSP Examples. </description> <jsp-config> <taglib> <taglib-uri>myhello</taglib-uri> <taglib-location>/WEB-INF/hellotag.tld</taglib-location> </taglib> <taglib> <taglib-uri>date</taglib-uri> <taglib-location>/WEB-INF/datetag.tld</taglib-location> </taglib> </jsp-config> </web-app>
那么下面开始进行标签的使用操作很多的地方都在使用标签完成操作package com.demo; import java.io.*; import javax.servlet.*; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.*; public class AttributeTag extends TagSupport{ private String name; //接收属性的名称 private String scope; //接收属性的范围 @Override public int doStartTag() throws JspException { //判断属性是否存在 Object value = null; if("page".equals(this.scope)) { value = super.pageContext.getAttribute(this.name,PageContext.PAGE_SCOPE); } if("request".equals(this.scope)) { value = super.pageContext.getAttribute(this.name,PageContext.REQUEST_SCOPE); } if("session".equals(this.scope)) { value = super.pageContext.getAttribute(this.name,PageContext.SESSION_SCOPE); } if("application".equals(this.scope)) { value = super.pageContext.getAttribute(this.name,PageContext.APPLICATION_SCOPE); } if(value == null) { //表示现在根本没有此属性 return TagSupport.SKIP_BODY; //没有属性不执行标签体 } else { return TagSupport.EVAL_BODY_INCLUDE; // 执行标签体 } } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } } <?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>firsttag</short-name> <!-- 标签库在tld中的描述 --> <tag> <name>present</name> <tag-class>com.demo.AttributeTag</tag-class> <body-content>JSP</body-content> <attribute> <name>name</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>scope</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib> <taglib> <taglib-uri>gz</taglib-uri> <taglib-location>/WEB-INF/gztag.tld</taglib-location> </taglib> <%@ page contentType="text/html; charset=GBK"%> <%@ taglib prefix="mytag" uri="gz"%> <html> <head><title>欢迎光临</title></head> <body> <% String scope = "session"; //假设现在判断的是session范围 session.setAttribute("username","我要做皇帝"); %> <mytag:present name="username" scope="<%=scope%>" > <h2><%=scope%> 范围存在属性,内容是:"${sessionScope.username}"</h2> </mytag:present> <mytag:present name="usernames" scope="request" > <h2>request 范围存在属性,内容是:"${requestScope.usernames}"</h2> </mytag:present> </body> </html>
这个时候完成了有标签的标签开发工作,这样JSP的功能之一,判断的功能就可以通过标签完成简化代码的开发了
这个标签操作就是根据返回值的数值,来决定我最终的操作是哪一种。
小结
TagSupport 类中有各种标签处理方法,根据其返回值进行相应方法的调用;
标签中可以存在标签体,但是必须通过EVAL_BODY_INCLUDE才可以执行标签体