使用反射机制给对象属性赋值

使用前提:

使用反射机制封装赋值操作,前提是dto中的属性名和表单提交的name字段是完全一样的。

问题描述:

封装页面数据到dto中时,比如增加和修改商品表是相同的操作,对商品表和用户表的增加和修改可能也是相同的需要,所以为了提高代码的复用性和方便处理相同的业务逻辑,有必要有一个方法,根据用户传递的实体类,可以自动装配实体类和表单中数据的对应关系。

解决步骤:

1.需要获得表单中提交的数据,封装为一个数据集
2.获取JavaBean中的所以set方法并封装为集合
3.根据JavaBean中的set方法和表单中的name字段进行类型匹配,即两个字符串完全一致时才可以进行赋值

实现方法的工具类:DtoSetUtils类
package org.jiazhong.demo.service;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.jiazhong.dao.DaoException;
public class DtoSetUtils {
	
	//给用户提供的调用接口,用户只需要将赋值的JavaBean和req传递过来,即可自动完成赋值操作
	public static <T> T getBeanFromRequest(Class<T> beanClass,HttpServletRequest req) throws Exception {
		List<Method> setMds = getSetMds(beanClass);
		// 截取到不包含set的方法名
		List<String> lists = getSubAttr(setMds);

		return setMyParameter(setMds, lists, req, beanClass);
	}

	//获得实体类的set方法名称
	private static <T> List<Method> getSetMds(Class<T> beanClass) {

		List<Method> list = new ArrayList<Method>();

		Method[] mds = beanClass.getMethods();// 获取元类对象所描述类的所有public方法的描述对象

		for (Method md : mds) {
			String mdName = md.getName();// 获取方法名称
			if (mdName.startsWith("set") && mdName.length() > 3 && md.getParameterCount() == 1
					&& Character.isUpperCase(mdName.charAt(3))) {
				list.add(md);
			}
		}
		return list;
	}

	//set方法名称小写,方便在request.getParameter(String)时调用
	private static List<String> getSubAttr(List<Method> setMds) {
		List<String> list = new ArrayList<String>();
		for (Method setmd : setMds) {
			String name = setmd.getName().substring(3).toLowerCase();
			list.add(name);
		}
		return list;
	}

	/**
	 * 	执行赋值操作前需要判断值的类型是什么,如果是字符串则可以直接赋值
	 * 	如果是字符串数字就需要转换为数字,如Integer.parseInt()等,所以
	 * 	在判断之后,才可以赋值
	 * @param <T>:泛型的类型
	 * @param argType:参数的类型
	 * @param value:参数值
	 * @return
	 */
	private static <T> T getValue(Class<T> argType, String value) {

		if (argType.equals(String.class)) {
			return (T) value;
		} else if (argType.equals(Integer.class) || argType.equals(int.class)) {
			return (T) Integer.valueOf(value);
		} else if (argType.equals(Byte.class) || argType.equals(byte.class)) {
			return (T) Byte.valueOf(value);
		} else if (argType.equals(Short.class) || argType.equals(short.class)) {
			return (T) Short.valueOf(value);
		} else if (argType.equals(Long.class) || argType.equals(long.class)) {
			return (T) Long.valueOf(value);
		} else if (argType.equals(Float.class) || argType.equals(float.class)) {
			return (T) Float.valueOf(value);
		} else if (argType.equals(Double.class) || argType.equals(double.class)) {
			return (T) Double.valueOf(value);
		} else if (argType.equals(Boolean.class) || argType.equals(boolean.class)) {
			return (T) Boolean.valueOf(value);
		} else

			throw new DaoException(argType + "类型暂时不匹配");
	}

	/**
	 * 	处理赋值操作的主业务
	 * @param <T>:泛型的类型
	 * @param setMds:获取的所有set方法
	 * @param lists:获取表单input提交的name名称
	 * @param req:请求
	 * @param clazz:元类
	 * @return
	 * @throws Exception
	 */
	private static <T> T setMyParameter(List<Method> setMds, List<String> lists, HttpServletRequest req, Class<T> clazz) throws Exception {
	//获取对象的无参构造方法,创建一个对象
		T bean = clazz.getConstructor().newInstance();
		for (Method setMd : setMds) {
			for (String list : lists) {
				/**
				 * 	获取JavaBean中的set方法但是不包含set的方法和表单中的name进行忽略大小写比较
				 */
				if (!list.isEmpty() && setMd.getName().substring(3).equalsIgnoreCase(list)) {
					try {
						//获取表单中name值
						String strValue = req.getParameter(list);
						/**
						 * 	防止有一些数据用户根本就没有添加,而进行赋值操作时出现空指针异常
						 */
						if (strValue != null) {
							// 根据set方法的参数类型,将字符串参数转换为set方法参数类型
							Object value = getValue(setMd.getParameterTypes()[0], strValue);
							/**如:dto.setName(req.getParameter("name))
							 * 	执行invoke方法
							 * setMd表示执行invoke的方法名,相当于setName
							 * bean表示执行invoke的setMd方法所属的具体类,相当于dto
							 * val表示赋的值,相当于req.getParameter(参数名)
							 */
							setMd.invoke(bean, value);
						}
					} catch (Exception e) {
						
					}
				}
			}
		}
		/**
		 * 	执行完毕要将bean返回,相当于调用者现在要使用杯子接杯水,将这个
		 * 	操作给了执行者,执行者使用这个杯子接满水之后需要将杯子给他的调用者
		 * 	否则调用者不知道你是否给我接没接
		 */
		return bean;
	}

}

调用工具类:
GoodsDto gd = DtoSetUtils.getBeanFromRequest(GoodsDto.class, req);
备注:

具体的dto和页面就不在此赘述了,这个工具完全使用于任何赋值的场景中。

出现的问题1:

遇到的问题可以获得set方法,表单中的数据也可以得到,但是在使用反射机制,执行invoke方法时候发现,不能赋值。
解决在工具类中已经做出详细结束,invoke(Object,args)方法的第一个参数是执行invoke的方法所属的对象,注意是对象,而不是其他什么。

出现的问题2:

获取set方法和传递表单中的数据都没有问题,但是在执行赋值操作时出错,日志记录显示的信息是sql语句获得的参数为空,即没有给dto中的属性赋值,其实就是没有没有将处理的结果返回给调用者,自己创建了一个对象。
还是借用前面接水的例子,调用者给了个杯子让接杯水,结果执行者自己造了个杯子接满水,并且还不将杯子给调用者,所以肯定得到null值。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值