修改后的BeanUtil更好的支持List Set 映射

通常从HTTPRequest中,可以通过BeanUtil自动将request中的参数映射到某个pojo中,如
BeanUtil.populate(request.getParameterMap(), obj);
但当客户端提交的form参数如下时,会出现问题
detail[0].name='123'&detail[0].age=14

另外,如果服务器端obj的属性是Set而不是List,则BeanUtil不支持

我实现了PropertyUtilsBean2,避免了上述问题
如下使用

Map map = new HashMap();
		map.put("code", "11212");
		map.put("amount", "1222222");
		map.put("details[0].vendorName", "vender");
		map.put("details[0].updateDate", "2001-1-1");
		map.put("details[1].vendorName", "vender33");
		map.put("details[1].updateDate", "2001-1-5");

		Order order = new Order();
		ConvertUtilsBean convertBean = new ConvertUtilsBean();
		
		BeanUtilsBean util = new BeanUtilsBean(convertBean,new PropertyUtilsBean2() );
		try {
			util.populate(order, map);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		System.out.println(order.getAmount());
		System.out.println(order.getDetails().size());



代码如下,关键部分是getIndexedProperty方法里的
if ((value instanceof java.util.Set)){}
else if (value instanceof java.util.List){}
/**
 * 对原有PropertyUtilsBean,进行了改善,增强了对list映射,增加set的映射支持,参考getIndexedProperty方法
 * @author lijiaz
 *
 */
public class PropertyUtilsBean2 extends PropertyUtilsBean {
	public PropertyUtilsBean2() {
		super();
	}

	private Object invokeMethod(Method method, Object bean, Object[] values)
			throws IllegalAccessException, InvocationTargetException {
		if (bean == null) {
			throw new IllegalArgumentException(
					"No bean specified "
							+ "- this should have been checked before reaching this method");
		}

		try {

			return method.invoke(bean, values);

		} catch (NullPointerException cause) {
			// JDK 1.3 and JDK 1.4 throw NullPointerException if an argument is
			// null for a primitive value (JDK 1.5+ throw IllegalArgumentException)
			String valueString = "";
			if (values != null) {
				for (int i = 0; i < values.length; i++) {
					if (i > 0) {
						valueString += ", ";
					}
					if (values[i] == null) {
						valueString += "<null>";
					} else {
						valueString += (values[i]).getClass().getName();
					}
				}
			}
			String expectedString = "";
			Class[] parTypes = method.getParameterTypes();
			if (parTypes != null) {
				for (int i = 0; i < parTypes.length; i++) {
					if (i > 0) {
						expectedString += ", ";
					}
					expectedString += parTypes[i].getName();
				}
			}
			IllegalArgumentException e = new IllegalArgumentException(
					"Cannot invoke " + method.getDeclaringClass().getName()
							+ "." + method.getName() + " on bean class '"
							+ bean.getClass() + "' - "
							+ cause.getMessage()
							// as per https://issues.apache.org/jira/browse/BEANUTILS-224
							+ " - had objects of type \"" + valueString
							+ "\" but expected signature \"" + expectedString
							+ "\"");
			if (!BeanUtils.initCause(e, cause)) {

			}
			throw e;
		} catch (IllegalArgumentException cause) {
			String valueString = "";
			if (values != null) {
				for (int i = 0; i < values.length; i++) {
					if (i > 0) {
						valueString += ", ";
					}
					if (values[i] == null) {
						valueString += "<null>";
					} else {
						valueString += (values[i]).getClass().getName();
					}
				}
			}
			String expectedString = "";
			Class[] parTypes = method.getParameterTypes();
			if (parTypes != null) {
				for (int i = 0; i < parTypes.length; i++) {
					if (i > 0) {
						expectedString += ", ";
					}
					expectedString += parTypes[i].getName();
				}
			}
			IllegalArgumentException e = new IllegalArgumentException(
					"Cannot invoke " + method.getDeclaringClass().getName()
							+ "." + method.getName() + " on bean class '"
							+ bean.getClass() + "' - "
							+ cause.getMessage()
							// as per https://issues.apache.org/jira/browse/BEANUTILS-224
							+ " - had objects of type \"" + valueString
							+ "\" but expected signature \"" + expectedString
							+ "\"");
			if (!BeanUtils.initCause(e, cause)) {

			}
			throw e;

		}
	}
	
	Method getReadMethod(Class clazz, PropertyDescriptor descriptor) {
        return (MethodUtils.getAccessibleMethod(clazz, descriptor.getReadMethod()));
    }

	public Object getIndexedProperty(Object bean, String name, int index)
			throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException {

		if (bean == null) {
			throw new IllegalArgumentException("No bean specified");
		}
		if (name == null || name.length() == 0) {
			if (bean.getClass().isArray()) {
				return Array.get(bean, index);
			} else if (bean instanceof List) {
				return ((List) bean).get(index);
			}
		}
		if (name == null) {
			throw new IllegalArgumentException(
					"No name specified for bean class '" + bean.getClass()
							+ "'");
		}

		// Handle DynaBean instances specially
		if (bean instanceof DynaBean) {
			DynaProperty descriptor = ((DynaBean) bean).getDynaClass()
					.getDynaProperty(name);
			if (descriptor == null) {
				throw new NoSuchMethodException("Unknown property '" + name
						+ "' on bean class '" + bean.getClass() + "'");
			}
			return (((DynaBean) bean).get(name, index));
		}

		// Retrieve the property descriptor for the specified property
		PropertyDescriptor descriptor = getPropertyDescriptor(bean, name);
		if (descriptor == null) {
			throw new NoSuchMethodException("Unknown property '" + name
					+ "' on bean class '" + bean.getClass() + "'");
		}

		// Call the indexed getter method if there is one
		if (descriptor instanceof IndexedPropertyDescriptor) {
			Method readMethod = ((IndexedPropertyDescriptor) descriptor)
					.getIndexedReadMethod();
			readMethod = MethodUtils.getAccessibleMethod(bean.getClass(),
					readMethod);
			if (readMethod != null) {
				Object[] subscript = new Object[1];
				subscript[0] = new Integer(index);
				try {
					return (invokeMethod(readMethod, bean, subscript));
				} catch (InvocationTargetException e) {
					if (e.getTargetException() instanceof IndexOutOfBoundsException) {
						throw (IndexOutOfBoundsException) e
								.getTargetException();
					} else {
						throw e;
					}
				}
			}
		}

		// Otherwise, the underlying property must be an array
		Method readMethod = getReadMethod(bean.getClass(), descriptor);
		if (readMethod == null) {
			throw new NoSuchMethodException("Property '" + name + "' has no "
					+ "getter method on bean class '" + bean.getClass() + "'");
		}

		// Call the property getter and return the value
		Object value = invokeMethod(readMethod, bean, new Object[0]);
		

		if (!value.getClass().isArray()) {
			if ((value instanceof java.util.Set)) {
				//Set并不支持通过index来获取,所以必须循环,导致有些效率问题,然后对于目前应用来说问题并不大
				Set set = (java.util.Set) value;
				Type returnType = readMethod.getGenericReturnType();
				Type acturalType = ((ParameterizedType)returnType).getActualTypeArguments()[0];
				
				
				while(set.size()<=index){
					try {
						set.add(((Class)acturalType).newInstance());
					} catch (InstantiationException e) {
						throw new RuntimeException(e.getMessage());
					}
				}
				Iterator it = set.iterator();
				int i=0;
				Object o = null;
				while(i<=index){
					it.hasNext();
					o = it.next();
					i++;
				}
				return o;
				
			} else if (value instanceof java.util.List){
				// get the List's value
				List list = (java.util.List) value;
				Type returnType = readMethod.getGenericReturnType();
				Type acturalType = ((ParameterizedType)returnType).getActualTypeArguments()[0];
				
				
				while(list.size()<=index){
					try {
						list.add(((Class)acturalType).newInstance());
					} catch (InstantiationException e) {
						throw new RuntimeException(e.getMessage());
					}
				}
				return list.get(index);
			}
			else{
				throw new IllegalArgumentException("Property '" + name
						+ "' is not indexed on bean class '" + bean.getClass()
						+ "'");
			}
		} else {
			// get the array's value
			try {
				return (Array.get(value, index));
			} catch (ArrayIndexOutOfBoundsException e) {
				throw new ArrayIndexOutOfBoundsException("Index: " + index
						+ ", Size: " + Array.getLength(value)
						+ " for property '" + name + "'");
			}
		}

	}
}




你可能感兴趣的:(apache,jdk,bean,应用服务器)