使用到JSP中的自定义标签技术时,关于自定义标签对应的处理器类的属性设置:如果属性类型是基本类型,JSP容器可以自动完成类型转换,并调用符合Bean标准的setter方法。
例如:我们定义一个简单的标签处理器类FirstPersonTag,它负责向JSP页面输出一段信息,包括他自己的名字、年龄、性别。
package com.neuqsoft.demo.tag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class FirstPersonTag extends SimpleTagSupport{ private String name; private int age; private boolean male; public void setAge(int age) { this.age = age; } public void setMale(boolean male) { this.male = male; } public void setName(String name) { this.name = name; } public void doTag() throws JspException, IOException { super.doTag(); JspWriter out=getJspContext().getOut(); out.println("Name:"+name); out.println("Age:"+age); out.println("Sex:"+(male?"Male":"Female")); } }下面是它所在的标签库描述文件demo1.tld的定义:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.1</tlib-version> <jsp-version>1.2</jsp-version> <short-name>Demo</short-name> <uri>http://demo1.neuqsoft.com</uri> <display-name>Neuqsoft CustomTag Demo</display-name> <description>Demo</description> <tag> <name>firstPerson</name> <tag-class>com.neuqsoft.demo.tag.FirstPersonTag</tag-class> <body-content>NONE</body-content> <display-name>table</display-name> <description>The First PersonTag</description> <attribute> <name>name</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The name of this Person</description> </attribute> <attribute> <name>age</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The age of this Person</description> </attribute> <attribute> <name>male</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The sex of this Person</description> </attribute> </tag> </taglib>firstPerson标签在JSP页面中的使用方法:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <%@ page language="java" pageEncoding="gb2312"%> <%@ taglib uri="http://demo1.neuqsoft.com" prefix="demo"%> <html> <head> <title>自定义标签演示</title> </head> <body> <demo:firstPerson name="Flixy" age="26" male="false"></demo:firstPerson> </body> </html>上面代码的输出结果为 :Name:Flixy Age:26 Sex:Female
如果注意demo1.tld的内容的话,可以看到每一个属性定义(<attribute>元素)中都有<rtexprvalue>true</rtexprvalue>被指定,rtexprvalue实际上是Runtime Expression Value的所写,如果它的值为true,说明此属性值可以接受一个EL表达式。因此对于firstPerson这个标签我们还可以这样使用。
firstPerson标签在JSP页面中的使用方法2:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <%@ page language="java" pageEncoding="gb2312"%> <%@ taglib uri="http://demo1.neuqsoft.com" prefix="demo"%> <html> <head> <title>自定义标签演示</title> </head> <body> <% request.setAttribute("age",new Integer(25)); request.setAttribute("male",Boolean.valueOf(true)); %> <demo:firstPerson name="Flixy" age="${age}" male="${male}"></demo:firstPerson> </body> </html>上面代码的输出结果为 :Name:Flixy Age:25 Sex:Male
注意:实际应用中request的属性对应该是在Action中设置的,JSP页面作为视图层只负责展现数据。
但是你可能认为上面两个例子演示的使用EL表达式与否并无本质的差异,相反使用EL表达式倒显得笨拙一些,但是考虑如下的情形,假如标签处理器类中的属性不是基本类型呢?这个时候JSP容器是无法完成转换的,因为属性的类型很可能是你自己定义的。不妨看下面的例子,在这个例子中Person的性别我们不是用一个boolean值表示,而是用一个自定义的对象Sex,Sex的源码如下:
package com.neuqsoft.demo.tag; public class Sex{ private boolean isMale; public Sex(boolean isMale) { super(); this.isMale = isMale; } public boolean isMale() { return isMale; } public void setMale(boolean isMale) { this.isMale = isMale; } }下面是Person标签处理器类的第二个版本:
package com.neuqsoft.demo.tag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class SecondPersonTag extends SimpleTagSupport { private String name; private int age; private Sex sex=new Sex(false); public void setAge(int age) { this.age = age; } public void setName(String name) { this.name = name; } public void setSex(Sex sex) { this.sex = sex; } public void doTag() throws JspException, IOException { super.doTag(); JspWriter out=getJspContext().getOut(); if(sex==null)sex=new Sex(true); out.println("Name:"+name); out.println("Age:"+age); out.println("Sex:"+(sex.isMale()?"Male":"Female")); } }其对应的标签定义片段:
<tag> <name>secondPerson</name> <tag-class>com.neuqsoft.demo.tag.SecondPersonTag</tag-class> <body-content>NONE</body-content> <display-name>table</display-name> <description>The First PersonTag</description> <attribute> <name>name</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The name of this Person</description> </attribute> <attribute> <name>age</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The age of this Person</description> </attribute> <attribute> <name>sex</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The sex of this Person</description> </attribute> </tag>由于SecondPersonTag的setSex方法的参数不是基本类型而是Sex,所以JSP容器不能自动完成类型转换,在这种情况下只能使用EL 表达式了,如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <%@ page language="java" import="com.neuqsoft.demo.tag.Sex" pageEncoding="gb2312"%> <%@ taglib uri="http://demo1.neuqsoft.com" prefix="demo"%> <html> <head> <title>自定义标签演示</title> </head> <body> <%request.setAttribute("sex",new Sex(true)); %> <demo:secondPerson name="Flixy" age="75" sex="${sex}"></demo:secondPerson> </body> </html>显示结果:Name:Flixy Age:75 Sex:Male
使用内省,如果标签处理器类中没有符合Javabean规范的setter方法,可以使用内省告诉JSP容器怎么处理标签的属性赋值,这需要额外提供一个BeanInfo类,此类和标签处理器类在同一个包中,命名规则是标签处理器类类名+BeanInfo,例如假如标签处理器的完整类名为com.neuqsoft.demo.PersonTag,则BeanInfo类的完整类名应该是com.neuqsoft.demo.PersonTagBeanInfo,下面是一个例子,例子中是PersonTag的第三个版本ThirdPersonTag:
package com.neuqsoft.demo.tag; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class ThirdPersonTag extends SimpleTagSupport{ private String name; private int age; private Sex sex; public void sex(Sex _sex){ this.sex=_sex; } public void setName(String name){ this.name=name; } public void putAge(int age){ this.age=age; } public void doTag() throws JspException, IOException { super.doTag(); JspWriter out=getJspContext().getOut(); if(sex==null)sex=new Sex(true); out.println("Name:"+name); out.println("Age:"+age); out.println("Sex:"+(sex.isMale()?"Male":"Female")); } }其对应的标签定义片段:
<tag> <name>thirdPerson</name> <tag-class>com.neuqsoft.demo.tag.ThirdPersonTag</tag-class> <body-content>NONE</body-content> <display-name>table</display-name> <description>The First PersonTag</description> <attribute> <name>_name</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The name of this Person</description> </attribute> <attribute> <name>_age</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The age of this Person</description> </attribute> <attribute> <name>_sex</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description>The sex of this Person</description> </attribute> </tag>注意:我故意在每一个属性name值前面加上了下划线,例如_name、_age、_sex,显然ThirdPersonTag这个标签处理器类中没用对应的setter方法,那么我是如何告诉JSP容器找到合适的方法设置属性值的呢?答案是BeanInfo类,下面是ThirdPersonTagBeanInfo类的源码:
package com.neuqsoft.demo.tag; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.beans.SimpleBeanInfo; import java.util.ArrayList; import java.util.List; public class ThirdPersonTagBeanInfo extends SimpleBeanInfo { public PropertyDescriptor[] getPropertyDescriptors() { List proplist = new ArrayList(); try { proplist.add(new PropertyDescriptor("_sex",ThirdPersonTag.class,null,"sex")); proplist.add(new PropertyDescriptor("_age",ThirdPersonTag.class,null,"putAge")); proplist.add(new PropertyDescriptor("_name",ThirdPersonTag.class,null,"setName")); } catch (IntrospectionException e) { e.printStackTrace(); } return (PropertyDescriptor[]) proplist.toArray(new PropertyDescriptor[0]); } }它的getPropertyDescriptors返回一组属性描述符,描述了每一个属性应该被怎样设置到标签处理器类中,例如_age属性对应着putAge方法,尽管这个方法不符合Javabean的setter方法规范。
ThirdPersonTag应用示例 :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <%@ page language="java" import="com.neuqsoft.demo.tag.Sex" pageEncoding="gb2312"%> <%@ taglib uri="http://demo1.neuqsoft.com" prefix="demo"%> <html> <head> <title>自定义标签演示</title> </head> <body> <%request.setAttribute("sex",new Sex(true)); %> <demo:thirdPerson _name="FlixyDemo3" _age="75" _sex="${sex}"></demo:thirdPerson> </body> </html>显示结果:Name:FlixyDemo3 Age:75 Sex:Male
相关资源:敏捷开发V1.0.pptx