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的原理了,我会晕掉的。
为了彻底解决这个问题,我就自己写了一个类,采用递归方式。下来来分析下

  1. 首先需要一个通过参数获取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();
        }
    }
}

这个方法主要就是根据参数的规则,然后判断数据的类型,然后进行对应的转化,这个里面用了递归,原因大家应该知道,我就不多说了。