Axis2 code generator Stub调用以及生成的衍生对象与原始对象的转换

96
jiuyibuzui
2016.10.29 12:37* 字数 299

开发中使用Axis2编写WebService的的时候,通常会使用Axis2 code genarator来进行代码的自动生成用以简化客户端的调用。
假设我有以下一个WebService:

public class UserService {
    public User getUserByUserName(String userName) {
        // do something, and return a User object
        return user;
    }
}

其中User类的定义如下:

public class User {
    private char[] address;

    private Integer age;

    private String userName;

    public char[] getAddress() {
        return address;
    }

    public Integer getAge() {
        return age;
    }

    public String getUserName() {
        return userName;
    }

    public void setAddress(char[] address) {
        this.address = address;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String toString() {
        return "userName: " + userName + "age: " + age + "address: " + new String(address);
    }
}

这时候客户端的调用就会变成如下所示:

GetUserByName method = new GetUserByName();
method.setUserName("somebody");
GetUserByNameResponse response = new UserServiceStub().getUserByName(method);
// 获取返回值
Object object = response.get_return();

大家可能会自然而然的认为object的类型就是User类型,但object的实际类型是com.service.stub.UserServiceStub.User,并不是我们的想要的User类型。
此时我们就称response.get_return()的返回对象为衍生对象,它的类型为衍生类型。
衍生类型的定义大致如下:

public class User implements org.apache.axis2.databinding.ADBBean {
    protected java.lang.String userName;
    // other fields and their getters, setters
    
    public static UserDTO parse(javax.xml.stream.XMLStreamReader reader) throws java.lang.Exception
}

从上面可以看到衍生类型其实包含了原始类型的所有的属性和方法,只不过访问属性可能不一样。
所以我们可以利用反射来进行衍生对象与原始对象的转换,代码如下:

// t1是衍生类型的实例
// c2是原始类型
public static <T1, T2> T2 convertObject(T1 t1, Class<T2> c2) throws Exception {
    // 创建原始对象实例
    T2 t2 = (T2) c2.newInstance();
    Class<?> c1 = t1.getClass();
    // 获取原始类型的所有属性
    Field[] fields = c2.getDeclaredFields();

    // 针对于每一个属性,使用getter方法去衍生对象中取值
    // 并且使用setter方法赋值给原始对象
    for (Field field : fields) {
        // 原始对象的属性名与setter方法使用驼峰标识,以便于相互两者相互查找
        String camelFieldName = field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
        // 获取衍生对象的具体属性的getter方法对象
        Method methodT2 = c2.getDeclaredMethod("set" + camelFieldName, field.getType());
        // 获取原始对象的具体属性的setter方法对象
        Method methodT1 = c1.getDeclaredMethod("get" + camelFieldName);
        // 调用原始对象的setter方法,并且将衍生对象的getter的返回值作为参数
        methodT2.invoke(t2, methodT1.invoke(t1));
    } // for

    return t2;
}

方法的性能还是较高的,实际测试在700us左右可以完成转换。
如果想采用其他方式转换,可以参考这篇:
http://blog.csdn.net/10km/article/details/48657959

随笔