使用到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