JavaWeb开发中form、ajax提交数据Model转化
问题
最近学习MongoDB数据库,作为java开发的我,当然需要做个小的web程序来测试一番了。在html中我采取ajax提交方式,因为我要模拟各种类型的数据,基础数据类型、数组、对象等。然而,最终发现了个不同的地方:Form和ajax提交数据,在HttpServletRequest中尽然参数名有所不同。
数据类型 | form | ajax |
基础数据 | para=value | para=value |
数组 | para[]={“aaa”,”bbb”} | para[][]={“aaa”,”bbb”} |
对象 | obj.sex=女(和基础数据一样,只不过用了obj.) | obj[sex]=女 |
对象数组 | obj[0].sex | obj[0][sex]=女 |
form提交,以上的参数方式,需要在input的name属性定义,常用的都是springmvc的数据绑定;ajax提交,参数来自data提交的对象的属性。
$.ajax({
type: "post",
dataType: "json",
url: "${ctx}/api/manage/save",
data: {
test: ['aab', 'bbb', 'ccc'],
table: 'tableName',
fields: [{
'field': 'f',
'type': 't',
'desc': 'd'
},
{
'field': 'f1',
'type': 't1',
'desc': 'd1'
]
}
}).success(function(data) {
alert(data.msg);
});
如上,就是一个ajax提交。
解决
发现了这个差异化,起始也没什么。但是在提交的时候,获取数据并解析有时候确实有些麻烦,即是spring等框架能够完美支持,但是还是应该搞懂原理。所以我也不打算去看spring的原理了,我会晕掉的。
为了彻底解决这个问题,我就自己写了一个类,采用递归方式。下来来分析下
- 首先需要一个通过参数获取T的一个方法,如下
public static <T> T getModel(Map<String, String[]> map, Class<T> clazz) {
Map<String, Object> jsonMap = new HashMap<String, Object>();
for (String key : map.keySet()) {
String[] values = map.get(key);
//$.ajax提交data:{arr:['aaa','bbb']},到这里key是arr[][]
if (key.endsWith("[]"))
key = key.substring(0, key.length() - 2);
parseKey(key, values, clazz, jsonMap);
}
return JSON.parseObject(JSON.toJSONString(jsonMap), clazz);
}
在这个方法中有两点:
1、ajax提交数组[][],需要去掉一个保持key的一致性
2、将Map转化为T对象,这里是通过fastjson来做的转化(现将Map转成json,然后再讲json转回T,因为直接转化有点难度)
parseKey方法
private static void parseKey(String key, String[] values, Class<?> clazz,
Map<String, Object> jsonMap) {
if (hasSubClass(key)) {//数组或对象的对象
String field = key.substring(0, key.indexOf("["));
String classField = "";
if (key.contains(".")) { //将form中的. 统一转化为[]来操作
key = key.replace("].", pattern).replace(".", pattern);
key = key + "]";
}
if (key.indexOf(pattern) != key.lastIndexOf(pattern)) {//可能是数组对象
classField = key.substring(key.indexOf(pattern) + 2,
key.length()).replaceFirst("]", "");
} else {
classField = key.substring(key.indexOf(pattern) + 2,
key.length() - 1);
}
if (jsonMap.get(field) == null) {
jsonMap.put(field, new ArrayList<Map<String, Object>>());
}
List<Map<String, Object>> list = (List) jsonMap.get(field);
int i = Integer.parseInt(key.substring(field.length() + 1,
field.length() + 2)) + 1;
for (int j = 0; j < i; j++) {
try {
list.get(j);
continue;
} catch (Exception e) {
list.add(j, new HashMap<String, Object>());
}
}
Class<?> subClass = null;
try {
ParameterizedType cl = (ParameterizedType) clazz
.getDeclaredField(field).getGenericType();
subClass = (Class<?>) cl.getActualTypeArguments()[0];
parseKey(classField, values, subClass, list.get(i - 1));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
} else {//基本数据或对象
try {
load(key, values, clazz, jsonMap);
} catch (Exception e) {
e.printStackTrace();
}
}
}
这个方法主要就是根据参数的规则,然后判断数据的类型,然后进行对应的转化,这个里面用了递归,原因大家应该知道,我就不多说了。