打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
反射的应用 将form表单的数据自动封装为对象
反射的应用 将form表单的数据自动封装为对象
博客分类: java基础
BeanCC++C#
我们经常做表单提交,然后把一大堆页面传过来的参数一一通过set方法赋值到对象中;
还经常遇到一个表单提交同一个类的多个对象,
甚至遇到:一个表单提交多种不同类的对象。
学习完反射后,很希望做一个比较通用的工具类,不再每次为上面的事情做重复劳动。
例如:页面有以下输入框:
<input type="text" name="name"  value="Jack"/>
<input type="text" name="name"  value="Mike"/>
<input type="text" name="name"  value="Rose"/>
<input type="text" name="age"  value="10"/>
<input type="text" name="age"  value="21"/>
<input type="text" name="age"  value="22"/>
<input type="text" name="birthday"  value="1978-07-22"/>
<input type="text" name="birthday"  value="1989-07-21 05:33"/>
<input type="text" name="birthday"  value="1999-08-21 23:33:12"/>
希望可以通过工具类,自动获得List<Person>,这个List有3个Person对象,
Person 1 : Jack,10,1978-07-22
Person 2 : Mike,21,1989-07-21 05:33
Person 3 : Rose,22,1999-08-21 23:33:12
第一步-准备工作 将字符串变为合适的数据类型
页面传过来的,都是String,而我们的bean里面的属性,是五花八门的数据类型。
我们首先需要准备一些小方法,将一个String的值转化成我们需要的数据类型的值。
Java代码 
 
public final static Map<String, String> toTypeMethods;
static {
//支持的转换类型:暂时为boolean,byte,char,int,long,float,double及他们的包装类 + String,java.util.Date,BigDecimal这几种类型
toTypeMethods = new HashMap<String, String>();
toTypeMethods.put("boolean", "toBoolean");
toTypeMethods.put("byte", "toByte");
toTypeMethods.put("char", "toString");
toTypeMethods.put("character", "toString");
toTypeMethods.put("string", "toString");
toTypeMethods.put("int", "toInteger");
toTypeMethods.put("integer", "toInteger");
toTypeMethods.put("long", "toLong");
toTypeMethods.put("float", "toFloat");
toTypeMethods.put("double", "toDouble");
toTypeMethods.put("date", "toDate");
toTypeMethods.put("bigdecimal", "toBigDecimal");
}
/**
* 这个方法的作用是:告诉我对象的属性、字符串,
* 这样我就可以将字符串转化成属性对应的数据类型的值了。
* 例如:在类中Person的birthday定义为Date,
* 我就会把"2010-10-01"转为整形的Date类型的2010-10-01
* 如果你把birthday定义为int,并传入了"2010-10-01",我的转换方法会返回null,
* 你也可以抛出异常,这个关键是看转换的方法实现,你可以按自己的要求更改
* @param field 对象的属性
* @param string 页面的参数
* @param 将string转化为属性类型的值
*/
public static Object toTypeValue(Field field, String string)
throws Exception{
String fieldTypename = field.getType().getSimpleName(); //属性的类型(不包含报名)
//通过属性的类型,从map中找到要调用的方法的名字,这些方法是将一个String的值转化成我们需要的数据类型的值
String methodName = toTypeMethods.get(fieldTypename.toLowerCase());
//获取方法
Method method =
BeanReflectUtil.class.
getDeclaredMethod(methodName, string.getClass());
//调用方法,返回属性类型的值
return method.invoke(null, string); //如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。
}
//下面这些小方法是为了将一个String的值转化成我们需要的数据类型的值
@SuppressWarnings("unused")
private static Boolean toBoolean(final String s) {
return NumberUtil.toBoolean(s, true);
}
@SuppressWarnings("unused")
private static Byte toByte(final String s) {
return NumberUtil.toByte(s, (byte)0);
}
@SuppressWarnings("unused")
private static String toString(final String s) {
return s;
}
@SuppressWarnings("unused")
private static Integer toInteger(final String s) {
return NumberUtil.toInt(s, 0);
}
@SuppressWarnings("unused")
private static Long toLong(final String s) {
return NumberUtil.toLong(s, 0);
}
@SuppressWarnings("unused")
private static Float toFloat(String s) {
return NumberUtil.toFloat(s, (float)0);
}
@SuppressWarnings("unused")
private static Double toDouble(String s) {
return NumberUtil.toDouble(s, 0.0);
}
@SuppressWarnings("unused")
private static Date toDate(String s) { //支持部分日期格式
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(s);
} catch(Exception e1) {
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(s);
}catch(Exception e2) {
try {
return new SimpleDateFormat("yyyy-MM-dd").parse(s);
} catch (Exception e3) {
return null;
}
}
}
}
@SuppressWarnings("unused")
private static BigDecimal toBigDecimal(String s) {
try {
return new BigDecimal(s);
} catch(Exception e) {
return new BigDecimal(0);
}
}
NumberUtil.toXXX是为了将String转换为其他数据类型,它们的实现很简单,以整形为例:
Java代码 
 
/***
* 将字符串变成整形
* @param value 源
* @param defaultInt 变成整形时若抛出异常则返回默认值
* @return
*/
public static int toInt(String value, int defaultInt) {
int result = 0;
try {
result = Integer.parseInt(value);
} catch(NumberFormatException e) {
result = defaultInt;
}
return result;
}
如何使用:
现在我在页面获得了"20",需要把"20"赋给age
Java代码 
 
//希望大家看看前一篇文章(1)发射getter And Setter 的基本内容:http://ivan0513.iteye.com/admin/blogs/728396
Person p = new Person();
//将字符串"20" 转换为Integer 20
Object age = toTypeValue(p.getClass().getDeclaredField("age"), "20");
//将整形20赋值给对象Person的age,这里我故意不使用setAge方法,因为以后我们从页面换取参数,
//我们又怎会知是哪个对象的哪个属性呢。需要通用的反射。
//invokeSetMethod在附件BeanReflectUtil.java中
BeanReflectUtil.invokeSetMethod(Person.class, "age", p, age);
//打印验证
System.out.println(p.getAge());
那么控制台就会打印出:
Java代码 
 
20
完成上面的工具方法,那么,离自动将form表单的参数封装成对象集合的路就不远了!
第二步-获取页面的参数,封装返回对象集合List
Java代码 
 
/***
* 从页面取关于这个bean的元素数组
* 页面与类的字段名称必须一致
* @param c 要从页面中获取哪个类的信息
* return Map 字段名,字段值数组
*/
public static Map<String, String[]> getFieldValues(HttpServletRequest request, Class<?> c) {
Map<String, String[]> fieldValues = new HashMap<String, String[]>();
//这个类有哪些属性
String[] fieldNames = BeanReflectUtil.getDeclaredFieldNames(c);
for(int i=0; i<fieldNames.length; i++) {
//循环属性,获取页面相应参数数组
String[] values = request.getParameterValues(fieldNames[i]);
fieldValues.put(fieldNames[i], values);
}
return fieldValues;
}
Java代码 
 
/**
* 返回潜在对象可能的个数
* 本方法假定假设以下条件成立
* 1.页面的参数可能不会有对象的所有属性,但至少存在1个,
* 即Person{name, age, birthday}在页面中,至少有<input type="text" name="age" value="20" />(以文本框为例,不一定是文本框)
* 2.在存在的前提下,不同属性的参数个数一样
* 即<input type="text" name="age" id="age1" />  <input type="text" name="name" id="name1" />
* <input type="text" name="age" id="age2" /> <input type="text" name="name" id="name2" />
* 其他特殊情况恕不支持,如:
* <input type="text" name="age" id="age1" />  <input type="text" name="name" id="name1" /> <input type="text" name="birthday" id="birthday1" />
* <input type="text" name="age" id="age2" /> <input type="text" name="name" id="name2" /> <!--有2个age,name,却只有1个birthday-->
* @param fieldValues
* @return
*/
public static int getParameterLenth(HttpServletRequest request, Class<?> c) {
int parameterLenth = 0;
String[] fieldNames = BeanReflectUtil.getDeclaredFieldNames(c);
for(int i=0; i<fieldNames.length; i++) {
String[] values = request.getParameterValues(fieldNames[i]);
if(values != null) {
parameterLenth = values.length;
break;
}
}
return parameterLenth;
}
Java代码 
 
/**
* 将页面元素自动封装成bean,而且是多个bean
* @param request
* @param c
* @return
* @throws Exception
* @throws NoSuchFieldException
*/
public static List<?> assembleObjectList(HttpServletRequest request, Class<?> c)
throws Exception, NoSuchFieldException {
Object[] objArray = null;
//1.获取页面元素(关于这个bean的页面元素)
Map<String, String[]> fieldValues = getFieldValues(request, c);
List objList = null;
if(fieldValues != null) {
//2.获取bean的数量
int objLength = getParameterLenth(request, c);
objArray = new Object[objLength];
objList = new ArrayList();
//3.生成实例
for(int i=0; i<objLength; i++) {
objArray[i] = c.newInstance();
objList.add(objArray[i]);
}
//为每个实例的每个元素赋值(如果页面有该参数数组)
Iterator<String> keyIt = fieldValues.keySet().iterator();
while(keyIt.hasNext()) {
String fieldName = keyIt.next();
Field field = c.getDeclaredField(fieldName); //获取参数对应的字段
String[] fieldValue = fieldValues.get(fieldName); //获取参数数组
if(fieldValue != null) {
for(int i=0; i<objArray.length; i++) { //循环:为每个对象的字段,附上参数数组的值(通过set方法)
//1.准备字段的Set方法
Method m = BeanReflectUtil.assembleSetMethod(c, field);
//2.页面的值(String类型)转变为该字段对应类型的值
Object fieldObj = BeanReflectUtil.toTypeValue(field, fieldValue[i]);
//3.调用Set方法
m.invoke(objArray[i], fieldObj); //为对象objArray[i]调用set方法,为上文中的field字段附上fieldObj这个值
}
}
}
}
//  return objArray;
return objList;
}
使用:
如页面中有:<form>
Html代码 
 
<input type="text" name="age" id="age1" />
<input type="text" name="name" id="name1" />
<input type="text" name="age" id="age2" />
<input type="text" name="name" id="name2" />
</form>
提交后,后台封装List<Person>,只需以下代码:
Java代码 
 
List<Person> list = (List<Person>) BaiscDataUtil.assembleObjectList(request, Person.class);
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
playframework学习笔记之表单提交,超链接提交与页面渲染
new一个对象的过程
Struts2标签之Checkbox详解
动态类
静态块与非静态块的区别
static关键字
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服