jsp(19)(二)(自定义标签)
自定义标签功能:
1.替换java脚本(目的为避免在页面中写java脚本。很多框架都有自定标签以更好的页面展示) 2.控制jsp某部分是否执行 3.控制整个页面是否执行 4.控制jsp页面内容重复执行 5.修改标签体的输出内容
传统自定义的标签(jsp2.0之前)处理器类需要实现Tag比较多的子接口(服务器会自动调用实现类,根据配置)
也可以继承Tag的多个实现类(比如:TagSupport,BodyTagSupport)

传统自定义标签执行过程:
1.请求jsp,会将jsp转换为servlet,如何解析标签如下:(可以通过查看解析后的servlet源码查看) 2.遇到自定义标签,首先实例化标签对应的处理器类。 3.调用setPageContex把页面对象(可以获得各个域的数据)传递给处理器类。 4.看标签是否有父标签,如果有,调用setParent方法将父标签(处理器类)对象传递给处理器类,如果没有传递null 5.完成上面的初始化,遇到开始标签,调用doStartTag方法 6.如果有标签体,一般执行标签体 7.遇到结束标签,执行doEndTag方法 8.整个标签执行完,一般不会调用release()方法释放标签所占资源。 9.继续执行jsp其他内容
自定义标签的发展历:(篮框表示过时接口jsp2.0之前的,又称传统标签接口)

新的替代标签接口是simpleTag又称为简单标签接口,自定义的标签处理器类只要继承接口的实现类SimpleTagSupport
执行过程:解析简单标签:
1.实例化标签处理器类 2.调用setJspContext()将页面对象传递给处理器类 3.调用setParent()将父标签处理器对象传递给处理器类 4.调用每个属性对应的set方法把属性值传递给标签处理器对象。(如果调用标签时设置了属性,需要给处理器类添加属性及对应的set方法。) (如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。) 5.调用setJspBody()将代表标签体的JspFragment对象传递给处理器类 6.执行标签,也就是调用doTag()方法
doTag()方法通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。
javax.servlet.jsp.tagext.JspFragment类,类中只定义了两个方法:
JSP2.0中定义,它的实例对象代表JSP页面中的一段符合语法规范不能包含JSP脚本元素的jsp代码片段。
getJspContext方法
用于返回代表调用页面的JspContext对象.
public abstract void invoke(java.io.Writer out)
用于执行JspFragment对象所代表的JSP代码片段(即输出标签体的数据)
参数out用于指定结果写入到哪个输出流中,如果传递给参数out的值为null,则将执行结果写入到jspWritter(JspContext.getOut())对象中。(写给浏览器)
这个方法可以
1.控制是否执行和输出标签体的内容(不调用JspFragment.invoke相当于忽略标签体内容,不输出标签体内容) 2.是否迭代执行标签体的内容或(重复调用JspFragment.invoke方法,标签体内容将会被重复执行 3.对标签体的执行结果进行修改后再输出。(调用invoke方法输出到StringWriter,然后获取修改后JspContext.getOut()得到jspWritter再输出。)
一个自定义标签有三部分组成:
1.标签处理器类,需要继承SimpleTagSupport类重写方法 2.一般在WEB-INF/目录下创建标签配置文档(自定义tld文件.tld,文件名一般和jsp标签前缀一致) 3.jsp中使用标签前,需要关联到标签文档,以及设置前缀。
补充:(tld:标签库描述符(Tag Library Descriptor)
关于标签的 url 值一种可以和配置对应的url 一致,一种是标签定义的实际目录 对于标签体输出默认invoke(null)参数null表示页面输出 属性赋值只支持8种基本类型自动转换(string转换成基本类型),如果有特殊类型需要使用脚本或者el表达式。
实例输出标签内容:
处理器类:
public class SimpleTagDemo1 extends SimpleTagSupport{ public void doTag() throws JspException, IOException { JspFragment jf = this.getJspBody(); //相当于jf.invoke(null); jf.invoke(this.getJspContext().getOut()); //这里如果不想输出标签体内容的话,只需要不调用invoke方法即可 }
标签配置:custom.tld
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>Example TLD with Body</short-name>
<url>http://www.xxx.com/xxx</url>//可把该文件的标签和该地址绑定,使用该文件中的标签只需要在jsp中指定该url。
<tag>
<name>Hello</name>
<tag-class>com.runoob.SimpleTagDemol</tag-class>
<body-content>scriptless</body-content>
</tag>
</taglib>
jsp:
<%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>//url的内容也可以是上面定义的url地址http://www.xxx.com/xxx <html> <head> <title>A sample custom tag</title> </head> <body> <ex:Hello>
xxxxxxxxxx
</ex:Hello> </body> </html>
实例:标签之后的内容不输出:
处理器类,其他部分略
public class SimpleTagDemo2 extends SimpleTagSupport{ public void doTag() throws JspException, IOException { //直接抛出异常就不会执行余下的jsp内容 throw new SkipPageException(); }
简略:
<body-content>empty</body-content> //配置 <simpletag:demo2/> //jsp
实例:标签体内容重复输出:
处理器类,其他部分略
public class SimpleTagDemo3 extends SimpleTagSupport{ public void doTag() throws JspException, IOException { JspFragment jf = this.getJspBody(); for(int i=0;i<5;i++){ jf.invoke(null); } }
实例:修改标签体内容输出:
处理器类,其他部分略
public class SimpleTagDemo3 extends SimpleTagSupport{ public void doTag() throws JspException, IOException { JspFragment jf = this.getJspBody(); StringWriter sw = new StringWriter(); jf.invoke(sw); String content = sw.toString(); content = content.toUpperCase(); this.getJspContext().getOut().write(content); }
自定义标签属性的使用:
public class PropertyTag extends SimpleTagSupport{
//属性必须在这定义和他的set方法(属性值是8种基本类型,会自动转换) private int count = 0; public void setCount(int count){ this.count = count; } public void doTag() throws JspException, IOException { JspFragment jf = this.getJspBody(); for(int i=0;i<count;i++){ jf.invoke(null); } }
配置:
<tag>
<name>demo</name>
<tag-class>com.weijia.propertytag.PropertyTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>count</name> //属性名字
<required>true</required> //是否是必须使用(在jsp中)
<rtexprvalue>true</rtexprvalue> //属性是否支持表达式和java脚本
</attribute>
</tag>
jsp:
<propertytag:demo count="9"> aaaaa </propertytag:demo>
如果使用其他类型的属性,需要使用表达式语言和脚本:
处理器类:
public class PropertyTag extends SimpleTagSupport{ //属性必须在这定义和他的set方法(属性值是8种基本类型,会自动转换) private Date count = null; public void setCount(Date count){ this.count = count; }
jsp页面的参数必须使用脚本语言:(ps:这个属性应该是一个地址,然后处理器类获得该地址的对象)
<propertytag:demo count="<%=new Date()%>"> aaaaa </propertytag:demo>
如果有多个属性的配置:
<attribute>
<name>attribute_name1</name>
<required>false</required>
<type>java.util.Boolean</type>
<fragment>false</fragment>
</attribute>
<attribute>
<name>attribute_name2</name>
<required>true</required>
<type>java.util.Date</type>
</attribute>
标签属性的一些补充:

补充:
JavaWeb学习篇之----自定义标签&&JSTL标签库详解
http://www.runoob.com/jsp/jsp-custom-tags.html

浙公网安备 33010602011771号