setProperty标签的实现让我头痛了一阵子,一个不好解决的问题就是类型转换,因为从标签中得到的属性值都是字符型的,要将这些字符型转换为字段对应的类型才可以将值正确的传递给方法或字段。
jsp:setProperty动作有下面四个属性:
属性
说明
name
name属性是必需的。它表示要设置属性的是哪个Bean。
property
property属性是必需的。它表示要设置哪个属性。有一个特殊用法:如果property的值是“*”,表示所有名字和Bean属性名字匹配的请求参数都将被传递给相应的属性set方法。
value
value属性是可选的。该属性用来指定Bean属性的值。字符串数据会在目标类中通过标准的valueOf方法自动转换成数字、boolean、Boolean、byte、Byte、char、Character。例如,boolean和Boolean类型的属性值(比如“true”)通过Boolean.valueOf转换,int和Integer类型的属性值(比如“42”)通过Integer.valueOf转换。
value和param不能同时使用,但可以使用其中任意一个。
param
param是可选的。它指定用哪个请求参数作为Bean属性的值。如果当前请求没有参数,则什么事情也不做,系统不会把null传递给Bean属性的set方法。因此,你可以让Bean自己提供默认属性值,只有当请求参数明确指定了新值时才修改默认属性值。
/**
* 类说明:标签处理类,仿JSP的setProperty标签
* 创建日期:2004-7-2
* 修改日期:2004-7-4
* 创建人: dever
*/
package cn.dever.tag;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.lang.reflect.*;
public class SetProperty extends TagSupport
{
private String name; //得到类名称
private String property; //得以属性名
private String method; //返回属性的方法名
private String value; //属性值
private String param; //设置请求参数名,以便从request中得到值
public void setName(String s) {
this.name = s;
}
public String getName(){return this.name;}
public void setProperty(String property)
{
this.property = property; //将属性名转换成获得属性的方法名
int length = property.length();
String temp=property.substring(0,1).toUpperCase()+property.substring(1,length);
this.method="set"+temp;
}
public String getProperty(){return this.property;}
public void setValue(String value)
{
this.value = value;
}
public String getValue(){return this.value;}
public void setParam(String param)
{
this.param = param;
}
public String getParam(){return this.param;}
public int doStartTag() throws JspTagException
{
if(this.property.equals("*")){ //如果property的属性为"*"就不做处理
return EVAL_BODY_INCLUDE;
}
else{
Object getInstance=pageContext.getAttribute(name); //得到类的实例
Class theClass = getInstance.getClass(); //得到当前实例的类型对象
try{
Method[] theMethods = theClass.getMethods();//得到该类的所有方法
Class[] typeParameter = new Class[]{}; //定义方法的参数类型数组
for(int i = 0; i < theMethods.length; i++) {
String methodString = theMethods[i].getName();
if(methodString.equals(this.method)){
typeParameter = theMethods[i].getParameterTypes(); //得到方法的形参数组
System.out.println(this.method);
}
}
Object paraValue = getParaObj(typeParameter[0]);
Object[] objParameter = new Object[]{paraValue}; //被调用方法的参数数组
Method methInstance = theClass.getMethod(method,typeParameter); //根据方法名称得到一个方法实例
/**
*在类实例中执行方法
*两个参数,第一个是指调用方法所属于的对象,第二个是传递的值对象列表。
*/
methInstance.invoke(getInstance,objParameter);
}
catch(NoSuchMethodException e){
throw new JspTagException(method+"() is not exist!");
}
catch(InvocationTargetException e){
System.out.print("Invocation Target Error!");
}
catch(IllegalAccessException e){
System.out.print("Illegal Access Error!");
}
catch(NullPointerException e){
System.out.print("Null Pointer Error!");
}
}
return EVAL_BODY_INCLUDE;
}
/**
*根据类型名称将参数值或字段转换成相应类型
*我只选了几个类型来实现,大家用的时候,需要把所有类型写全
*/
private Object getParaObj(Class type) throws JspTagException{
String typeName = type.getName();
Object para = new Object();
String temp=null;
//两者只能选一
if(this.value!=null && this.param!=null){
throw new JspTagException("select one of value or param!!");
}
else if(this.value!=null)
{
temp=this.value;
}
else if(this.param!=null){
temp=pageContext.getRequest().getParameter(this.param).toString();
}
//类型转换
if(typeName.equals("java.lang.String") ){
if(temp==null){
return "null";
}
para=String.valueOf(temp);
}
else if(typeName.equals("java.lang.Integer") || type==Integer.TYPE){
if(temp==null){
return Integer.valueOf("0");
}
para=Integer.valueOf(temp);
}
else if(typeName.equals("java.lang.Boolean") || type==Boolean.TYPE){
if(temp==null){
return null;
}
para=Boolean.valueOf(temp);
}
else{
System.out.println(typeName);
throw new JspTagException("Value type is lawless!");
}
return para;
}
}