首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

"person.username.firstname"类型参数目字符串自动组装成对象的原理

2012-11-07 
person.username.firstname类型参数字符串自动组装成对象的原理在使用Struts2、WebWork框架开发Web应用时

"person.username.firstname"类型参数字符串自动组装成对象的原理

在使用Struts2、WebWork框架开发Web应用时,JSP页中的表单项,常常会使用这样的参数名:

<input type="text" name="person.username" /><input type="password" name="person.password" />

?

甚至,可以有更多层次的,如:

<input type="text" name="person.username.firstname" /><input type="text" name="person.username.lastname" />

?
上面第一例,在后端Java代码中,自然有一个Person类与之对应。其中,这个Person类包含2个属性:username, password,还有必要的Setter和Getter方法。
上面第二例,同样有一个Person类与之相对应,而Person类中包括了一个Username类型的属性"username";而在Username类里,有firstname和lastname两个属性。同样,相应的Setter和Getter方法是必不可少的。
那么,那些框架是怎么自动将型如"person.username.firstname"的字符串,组装成相应的对象(如Person对象)的呢?
请看以下代码:

/* * Copyright (c) 2002-2003 by OpenSymphony * All rights reserved. */package com.opensymphony.provider.bean;import com.opensymphony.provider.BeanProvider;import com.opensymphony.provider.ProviderConfigurationException;import java.beans.PropertyDescriptor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.StringTokenizer;/** * BeanProvider implementation for accessing properties. * * Can handle a.b.c.d -> getA().getB().getC().getD(). * Access properties in this order: bean.getA(), bean.isA(), bean.a(), bean.a. * * Can also deal with setter methods. * * @author <a href="mailto:joe@truemesh.com">Joe Walnes</a> * @version $Revision: 1.1.1.1 $ */public class DefaultBeanProvider implements BeanProvider {    //~ Static fields/initializers /////////////////////////////////////////////    private static String GET = "get";    private static String SET = "set";    private static String IS = "is";    //~ Methods ////////////////////////////////////////////////////////////////    public boolean setProperty(Object object, String property, Object value) {        if ((property == null) || (object == null)) {            return false;        }        // Split out property on dots ( "person.name.first" -> "person","name","first" -> getPerson().getName().getFirst() )        StringTokenizer st = new StringTokenizer(property, ".");        if (st.countTokens() == 0) {            return false;        }        // Holder for Object at current depth along chain.        Object current = object;        try {            // Loop through properties in chain.            for (int i = 0; st.hasMoreTokens(); i++) {                String currentPropertyName = st.nextToken();                if (i < st.countTokens()) {                    // This is a getter                    current = invokeProperty(current, currentPropertyName);                } else {                    // Final property in chain, hence setter                    try {                        // Call setter                        Class cls = current.getClass();                        PropertyDescriptor pd = new PropertyDescriptor(currentPropertyName, current.getClass());                        pd.getWriteMethod().invoke(current, new Object[] {value});                        return true;                    } catch (Exception e) {                        return false;                    }                }            }            // Return holder Object            return true;        } catch (NullPointerException e) {            // It is very likely that one of the properties returned null. If so, catch the exception and return null.            return false;        }    }    public Object getProperty(Object object, String property) {        if ((property == null) || (object == null)) {            return null;        }        // Split out property on dots ( "person.name.first" -> "person","name","first" -> getPerson().getName().getFirst() )        StringTokenizer st = new StringTokenizer(property, ".");        if (st.countTokens() == 0) {            return null;        }        // Holder for Object at current depth along chain.        Object result = object;        try {            // Loop through properties in chain.            while (st.hasMoreTokens()) {                String currentPropertyName = st.nextToken();                // Assign to holder the next property in the chain.                result = invokeProperty(result, currentPropertyName);            }            // Return holder Object            return result;        } catch (NullPointerException e) {            // It is very likely that one of the properties returned null. If so, catch the exception and return null.            return null;        }    }    public void destroy() {    }    public void init() throws ProviderConfigurationException {    }    /**     * Convert property name into getProperty name ( "something" -> "getSomething" )     */    private String createMethodName(String prefix, String propertyName) {        return prefix + propertyName.toUpperCase().charAt(0) + propertyName.substring(1);    }    /**     * Invoke the method/field getter on the Object.     * It tries (in order) obj.getProperty(), obj.isProperty(), obj.property(), obj.property.     */    private Object invokeProperty(Object obj, String property) {        if ((property == null) || (property.length() == 0)) {            return null; // just in case something silly happens.        }        Class cls = obj.getClass();        Object[] oParams = {};        Class[] cParams = {};        try {            // First try object.getProperty()            Method method = cls.getMethod(createMethodName(GET, property), cParams);            return method.invoke(obj, oParams);        } catch (Exception e1) {            try {                // First try object.isProperty()                Method method = cls.getMethod(createMethodName(IS, property), cParams);                return method.invoke(obj, oParams);            } catch (Exception e2) {                try {                    // Now try object.property()                    Method method = cls.getMethod(property, cParams);                    return method.invoke(obj, oParams);                } catch (Exception e3) {                    try {                        // Now try object.property()                        Field field = cls.getField(property);                        return field.get(obj);                    } catch (Exception e4) {                        // oh well                        return null;                    }                }            }        }    }}

?

oscore-2.2.5中的类,代码不难,且有注释,我就不多解析了。如有疑问,请提出来,我尽力解决。

try { // Call setter Class cls = current.getClass(); PropertyDescriptor pd = new PropertyDescriptor(currentPropertyName, current.getClass()); pd.getWriteMethod().invoke(current, new Object[] {value}); return true; } catch (Exception e) { return false; }

这段不明白。。。

PropertyDescriptor 这个是什么?
try { // Call setter Class cls = current.getClass(); PropertyDescriptor pd = new PropertyDescriptor(currentPropertyName, current.getClass()); pd.getWriteMethod().invoke(current, new Object[] {value}); return true; } catch (Exception e) { return false; }

这段不明白。。。

PropertyDescriptor 这个是什么?

Java的一个类,用来获取Getter和Setter方法很方便。具体,请看JDK的文档相关说明:http://java.sun.com/j2se/1.5.0/docs/api/java/beans/PropertyDescriptor.html

热点排行