程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> SpringMVC——對Ajax的處理(包含 JSON 類型),springmvcjson

SpringMVC——對Ajax的處理(包含 JSON 類型),springmvcjson

編輯:JAVA綜合教程

SpringMVC——對Ajax的處理(包含 JSON 類型),springmvcjson


一、首先要搞明白的一些事情。

1.從客戶端來看,需要搞明白:

(1)要發送什麼樣格式的 JSON 數據才能被服務器端的 SpringMVC 很便捷的處理,怎麼才能讓我們寫更少的代碼,如何做好 JSON 數據和實體之間的對應。

(2)如何組織這些發送的數據。

2.從服務器端來看,需要搞明白:

(1)SpringMVC 如何返回 JSON 數據。

(2)SpringMVC 如何處理請求的復雜數據。

3.$.ajax 的幾個參數:

(1)contentType:

contentType: 'application/json;charset=utf-8',作為請求頭,用來告訴服務器消息的主體是序列化後的 JSON 字符串。除了低版本的 ie 浏覽器外,各大浏覽器都原生支持 JSON.stringify() 對對象進行序列化。

(2)dataType:預期服務器返回的數據類型。

4.SpringMVC 是如何處理 JSON 數據的

5.總體的思想:

(1)SpringMVC 能完成的,盡量借助於 SpringMVC,而不是我們手動的去解析。

(2)SpringMVC 解析不了的,盡量借助於第三方的 Jar 包來解析。

(3)SpringMVC 和 第三方 Jar 包解決不了的時候,我們再自己去解析。

 

二、想要搞明白第一個問題,前提是先要搞明白第一個問題:SpringMVC 是如何處理 JSON 數據的。

1.使用 HttpMessageConverter<T> 來處理  JSON 數據的。

Spring 的 HttpMessageConverter<T> 負責將請求信息轉換為一個對象,將對象輸出為響應信息。

2.API

(1)boolean canRead(Class<?> clazz, MediaType mediaType);

轉換器是否可將請求信息轉換為 clazz 類型的對象,同時支持指定的 MIME 類型,如: text/html,application/json 等。

(2)boolean canWrite(Class<?> clazz, MediaType mediaType);

轉換器是否可以將 clazz 類型的對象寫到響應中,響應支持的類型在 mediaType 中定義。

(3)List<MediaType> getSupportedMediaTypes();

改轉換器支持的 MediaType 類型。

(4)T read(Class<? extends T> clazz, HttpInputMessage inputMessage);

將請求信息流轉換為 clazz 類型的對象。

(5)void write(T t, MediaType contentType, HttpOutputMessage outputMessage)。

將 T 類型的對象寫到響應輸出流中,同時指定 MediaType。

3.實現類

3.從上圖可以看出,Spring 默認支持使用 Jackson來處理 JSON 問題。添加 Jackson Jar 包後,來看 RequestMappingHadlerAdapter 裝配的 HttpMessageConverter:

導入的 Jackson Jar 包:

4.具體的處理方法:

(1)使用 @RequestBody 和 HttpEntity<T> 對請求進行處理。

(2)使用 @ResponseBody 和 ResponseEntity<T> 對響應進行處理。

(3)@RequestBody 對處理方法的入參進行標注。

(4)@ResponseBody 對處理方法的簽名進行標注。

(5)HttpEntity<T> 和 ResponseEntity<T> 作為處理方法的入參使用。

具體的使用方法會在下面例子中進行說明。

5.@RequestBody 和 @ResponseBody 是可以同時使用的。

 

三、上面簡單介紹了 SpringMVC 是怎麼處理 JSON 數據的,現在來看第二個問題:發送什麼樣格式的 JSON 數據才能被服務器端的 SpringMVC 很便捷的處理,這裡主要指的是請求的 JSON 字符串和實體的映射。

以一個簡單的實體為例:Person

/** * @author solverpeng * @create 2016-08-12-10:50 */ public class Person { private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } @NotBlank(message = "人名不能為空") public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } Person.java

(1)對於簡單的一個Person 對象來說,我們甚至都不需要借助於 JSON 就可以完成請求的數據與實體之間的映射。

請求:

$("#testJson").click(function () {
    $.ajax({
        url: "testJson",
        type: "post",
        data: {
            name : "abc",
            age : "23"
        },
        success: function (result) {
            console.log(result);
        }
    });
});

handler 方法:

@RequestMapping("/testJson")
public Person testJson(Person person) {
    System.out.println("person:" + person);
    return person;
}

(2)對於Person數組來說,需要發送什麼樣的格式才能被 SpringMVC 直接處理?

請求:

$("#testJson6").click(function () {
    $.ajax({
        url: "testJson6",
        type: "post",
        data:'[{ "name": "Brett", "age":"12" }, { "name": "Jason", "age":"23" }, { "name": "Elliotte", "age":"33" }]',
        contentType: "application/json; charset=utf-8",
        success: function (result) {
            console.log(result);
        }
    });
});

handler 方法:

@RequestMapping("/testJson6")
public String testJson6(@RequestBody List<Person> persons) {
    System.out.println("persons:" + persons);
    return "success";
}

注意:

(1)需要指定 "contentType",同時需要注意的是:發送的請求數據不在 Form data 中,而是在 Request Payload 中。關於 [Request Payload] ,在後面說明。

(2)必須要指定 @RequestBody ,否則無法解析。

 

四、第三個問題:如何組織這些數據以及SpringMVC 如何處理這些數據,做好映射。

(1)說明:

上面說的兩個例子,僅僅是最簡單的一種形式。現在對其進行擴展,在四裡,所說的 SpringMVC 如何處理這些數據,不僅僅指的是SpringMVC,也包括SpringMVC處理不了,使用第三方來處理,或者第三方處理不了,我自己來處理。

同時這裡的數據也不僅僅指的 JSON 類型的數據。

(2)對於非表單的 Ajax 提交,這裡只提供比較簡單的一種方式。還是以上面的 Person 為例。

e1:

數據的組織與請求的發送:

var personList = [];
personList.push({name: "李四",age: "23"});
personList.push({name: "張三",age: "12"});
$("#testJson5").click(function () {
    $.ajax({
        type: "POST",
        url: "testJson5",
        data: JSON.stringify(personList),//將對象序列化成JSON字符串
        contentType: 'application/json;charset=utf-8', //設置請求頭信息
        success: function (data) {
        },
        error: function (res) {
        }
    });
});

handler 方法:

@RequestMapping("/testJson5")
public String testJson5(@RequestBody List<Person> persons) {
    System.out.println(persons);
    return "success";
}

(3)基於表單的 Ajax 提交。

提供一個序列化方法:

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

還有一種序列化方式:

★單表單情況:

表單:

<form action="" method="post">
    First Name:<input type="text" name="firstName" maxlength="12" size="12"/> <br/>
    Last Name:<input type="text" name="lastName" maxlength="36" size="12"/> <br/>
    Gender:<br/>
    Male:<input type="radio" name="gender" value="1"/><br/>
    Female:<input type="radio" name="gender" value="0"/><br/>
    Favorite Food:<br/>
    Steak:<input type="checkbox" name="foods" value="Steak"/><br/>
    Pizza:<input type="checkbox" name="foods" value="Pizza"/><br/>
    Chicken:<input type="checkbox" name="foods" value="Chicken"/><br/>
    <textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/>
    Select a Level of Education:<br/>
    <select name="education">
        <option value="Jr.High">Jr.High</option>
        <option value="HighSchool">HighSchool</option>
        <option value="College">College</option>
    </select><br/>
    Select your favorite time of day:<br/>
    <select size="3" name="tOfD">
        <option value="Morning">Morning</option>
        <option value="Day">Day</option>
        <option value="Night">Night</option>
    </select>

    <p><input type="submit"/></p>
</form>

對應的實體:

/** * @author solverpeng * @create 2016-08-16-11:14 */ public class Student { private String firstName; private String lastName; private Integer gender; private List<String> foods; private String quote; private String education; private String tOfD; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } public List<String> getFoods() { return foods; } public void setFoods(List<String> foods) { this.foods = foods; } public String getQuote() { return quote; } public void setQuote(String quote) { this.quote = quote; } public String getEducation() { return education; } public void setEducation(String education) { this.education = education; } public String gettOfD() { return tOfD; } public void settOfD(String tOfD) { this.tOfD = tOfD; } @Override public String toString() { return "Student{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", gender=" + gender + ", foods=" + foods + ", quote='" + quote + '\'' + ", education='" + education + '\'' + ", tOfD='" + tOfD + '\'' + '}'; } } Student.java

e1:使用 serializeObject()

序列化後的值:

JSON.stringify($('form').serializeObject()):

{"firstName":"jack","lastName":"lily","gender":"1","foods":["Pizza","Chicken"],"quote":"hello hello","education":"Jr.High","tOfD":"Day"}

請求:

$(function() {
    $('form').submit(function() {
        $.ajax({
            url : "testStudent",
            data : JSON.stringify($('form').serializeObject()),
            contentType : "application/json;charset=utf-8",
            type : "post",
            success : function (result) {
                console.log(result);
            }
        });
        return false;
    });
});

e11:SpringMVC自身進行處理

handler 方法:

@RequestMapping("/testStudent")
public String testStudent(@RequestBody Student student) {
    System.out.println(student);
    return "success";
}

e12:引入第三方 Jar 包進行處理。

准備:

導入 sl4j jar 包,同時添加 JsonUtil 工具類。

public final class JsonUtil { private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); /** * 將 POJO 轉換為 JSON */ public static <T> String toJson(T obj) { String json; try { json = OBJECT_MAPPER.writeValueAsString(obj); } catch(JsonProcessingException e) { LOGGER.error("convert POJO to JSON failure", e); throw new RuntimeException(e); } return json; } /** * 將 JSON 轉換為 POJO */ public static <T> T fromJson(String json, Class<T> type) { T pojo; try { pojo = OBJECT_MAPPER.readValue(json, type); } catch(IOException e) { LOGGER.error("convert JSON to POJO failure", e); throw new RuntimeException(e); } return pojo; } } JsonUtil.java

後端處理:

@RequestMapping("/testStudent")
public String testStudent(@RequestBody String inputBody) {
    Student student = JsonUtil.fromJson(inputBody, Student.class);
    System.out.println(student);
    return "success";
}

都可以正常打印 Student 對象。

e2:使用 serialize()

序列化後的值:

$('form').serialize():

firstName=jack&lastName=lily&gender=1&foods=Pizza&foods=Chicken&quote=hello+hello&education=Jr.High&tOfD=Day

請求:

$(function() {
    $('form').submit(function() {
        $.ajax({
            url : "testStudent",
            data : $('form').serialize(),
            type : "post",
            success : function (result) {
                console.log(result);
            }
        });
        return false;
    });
});

handler 方法:

@RequestMapping("/testStudent")
public String testStudent(Student student) {
    System.out.println(student);
    return "success";
}

可以正常打印 Student 對象。

e1 和 e2 對比說明:

e1提交的 JSON 數據,e2 提交的不是 JSON 格式的數據。e1 的請求參數存放在 [Request Payload] 中,而 e2 的請求參數存放在 Form Data 中。

★單表單復雜數據

表單還是上面的 Student 表單,但是在表單外增加了:

<span id="amount">33</span>

需求是:通過 Ajax 發送表單數據的同時,同時發送 "amount" 。

經過測試,我就直接說結論了,有興趣的童鞋可以自行探索,有新的發現歡迎和我交流。

結論:

不能對這樣的數據,指定 "contentType:application/json",否則後端SpringMVC或者第三方的Jar 包 不能進行自動的解析,增加了解析的復雜度,所以將 json 串傳入後台,在後台進行解析。

e1:serializeObject()

請求:

$(function() {
    $('form').submit(function() {
        $.ajax({
            url : "testStudent",
            data : {
                amount : $("#amount").text(),
                student : JSON.stringify($('form').serializeObject())
            },
            type : "post",
            success : function (result) {
                console.log(result);
            }
        });
        return false;
    });
});

後端處理:使用第三方工具類進行解析

@RequestMapping("/testStudent")
public String testStudent(@RequestParam("student") String studentStr, String amount) {
    Student student = JsonUtil.fromJson(studentStr, Student.class);
    System.out.println("student:" + student);
    System.out.println("amount:" + amount);
    return "success";
}

可以正常打印。

e2:serialize()

請求:

$(function() {
    $('form').submit(function() {
        $.ajax({
            url : "testStudent",
            data : {
                amount : $("#amount").text(),
                student : $('form').serialize()
            },
            type : "post",
            success : function (result) {
                console.log(result);
            }
        });
        return false;
    });
});

Handler 方法:

e1:嘗試讓 SpringMVC 來解析:

@RequestMapping("/testStudent")
public String testStudent(@RequestParam("student") Student student, String amount) {
    System.out.println("student:" + student);
    System.out.println("amount:" + amount);
    return "success";
}

結果:請求無法到達 handler 方法

e2:

@RequestMapping("/testStudent")
public String testStudent(Student student, String amount) {
    System.out.println("student:" + student);
    System.out.println("amount:" + amount);
    return "success";
}

結果:請求可以正常到達目標 Handler 方法,但是無法映射 Student 對象。

方案:自己解析,編寫自定義的類型轉換器:

public class String2StudentConverter implements Converter<String, Student>{
    @Override
    public Student convert(String source) {
        return InjectUtil.convert2Obj(source, Student.class);
    }
}

這裡我編寫了一個通用的類型轉換器:

用來轉換形如: 

firstName=jack&lastName=lily&gender=1&foods=Steak&foods=Pizza&quote=Enter+your+favorite+quote!&education=Jr.High&tOfD=Day 到 Student 對象。

/**
 * @author solverpeng
 * @create 2016-08-22-17:37
 */
public final class InjectUtil<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(InjectUtil.class);

    public static <T> T converter2Obj(String source, Class<T> tClass) {
        T t = null;
        try {
            t = tClass.newInstance();
            Map<String, Object> params = new HashMap<String, Object>();
            if(source != null && source.length() > 0) {
                String[] fields = source.split("&");
                for(String field : fields) {
                    String[] fieldKeyValue = field.split("\\=");
                    String fieldKey = fieldKeyValue[0];
                    String fieldValue = fieldKeyValue[1];
                    if (params.containsKey(fieldKey)) {
                        Object keyValueRetrieved = params.get(fieldKey);
                        if (keyValueRetrieved instanceof String) {
                            ArrayList<String> values = new ArrayList<>();
                            values.add(keyValueRetrieved.toString());
                            values.add(fieldValue);
                            params.put(fieldKey, values);
                        } else {
                            ((ArrayList<String>) keyValueRetrieved).add(fieldValue);
                        }
                    } else {
                        params.put(fieldKey, fieldValue);
                    }
                }
            }
            BeanUtils.populate(t, params);
        } catch(InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            LOGGER.error("String convert to Bean failure!", e);
        }
        return t;
    }

}

不要忘記在 SpringMVC 中添加自定義的轉換器。

e3:也可以在 handler 方法中來調用上面我編寫的通用的類型轉換器來完成解析。

@RequestMapping("/testStudent")
public String testStudent(@RequestParam("student") String studentStr, String amount) {
    System.out.println("studentStr:" + studentStr);
    System.out.println("amount:" + amount);
    return "success";
}

說明:對於復雜數據來說,我們借助不了 SpringMVC,只能借助於第三方,或是自己來編寫解析器來解析。

★多表單一次提交

表單數據:

<form action="" method="post" id="form2"> First Name:<input type="text" name="firstName" maxlength="12" size="12"/> <br/> Last Name:<input type="text" name="lastName" maxlength="36" size="12"/> <br/> Gender:<br/> Male:<input type="radio" name="gender" value="1"/><br/> Female:<input type="radio" name="gender" value="0"/><br/> &lt;%&ndash;Favorite Food:<br/> Steak:<input type="checkbox" name="foods" value="Steak"/><br/> Pizza:<input type="checkbox" name="foods" value="Pizza"/><br/> Chicken:<input type="checkbox" name="foods" value="Chicken"/><br/>&ndash;%&gt; <textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/> Select a Level of Education:<br/> <select name="education"> <option value="Jr.High">Jr.High</option> <option value="HighSchool">HighSchool</option> <option value="College">College</option> </select><br/> Select your favorite time of day:<br/> <select size="3" name="tOfD"> <option value="Morning">Morning</option> <option value="Day">Day</option> <option value="Night">Night</option> </select> <p><input type="submit"/></p> </form> <form action="" method="post" id="form1"> First Name:<input type="text" name="firstName" maxlength="12" size="12"/> <br/> Last Name:<input type="text" name="lastName" maxlength="36" size="12"/> <br/> Gender:<br/> Male:<input type="radio" name="gender" value="1"/><br/> Female:<input type="radio" name="gender" value="0"/><br/> &lt;%&ndash; Favorite Food:<br/> Steak:<input type="checkbox" name="foods" value="Steak"/><br/> Pizza:<input type="checkbox" name="foods" value="Pizza"/><br/> Chicken:<input type="checkbox" name="foods" value="Chicken"/><br/>&ndash;%&gt; <textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/> Select a Level of Education:<br/> <select name="education"> <option value="Jr.High">Jr.High</option> <option value="HighSchool">HighSchool</option> <option value="College">College</option> </select><br/> Select your favorite time of day:<br/> <select size="3" name="tOfD"> <option value="Morning">Morning</option> <option value="Day">Day</option> <option value="Night">Night</option> </select> </form> View Code

e1:

同時需要定義一個 Students 類:

public class Students {
    private List<Student> students;

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }
}

請求:

$('form').submit(function() {
    $.ajax({
        url : "testStudent",
        data : JSON.stringify({
            "students": [
                $('#form1').serializeObject()
                ,
                $('#form2').serializeObject()
            ]
        }),
        contentType:"application/json;charset=utf-8",
        type : "post",
        success : function (result) {
            console.log(result);
        }
    });
    return false;
});

handler 方法:

@RequestMapping("/testStudent")
public String testStudent(@RequestBody Students students) {
    for(Student student : students.getStudents()) {
        System.out.println("student:" + student);
    }
    return "success";
}

可以正常打印。 

e2:不額外增加類,即不定義 Students

請求:

$('form').submit(function() {
    $.ajax({
        url : "testStudent",
        data : JSON.stringify([
            $('#form1').serializeObject(),
            $('#form2').serializeObject()
        ]),
        contentType:"application/json;charset=utf-8",
        type : "post",
        success : function (result) {
            console.log(result);
        }
    });
    return false;
});

handler 方法:

e21:通過數組來接收

@RequestMapping("/testStudent")
public String testStudent(@RequestBody Student[] students) {
    for(Student student : students) {
        System.out.println("student: " + student);
    }
    return "success";
}

e22:通過 List 來接收

@RequestMapping("/testStudent")
public String testStudent(@RequestBody List<Student> students) {
   for(Student student : students) {
       System.out.println("student: " + student);
   }
   return "success";
}

★一個表單多個對象

表單對象如:

e1:

<form action="" method="post" id="form"> First Name:<input type="text" name="firstName" maxlength="12" size="12"/> <br/> Last Name:<input type="text" name="lastName" maxlength="36" size="12"/> <br/> Gender:<br/> Male:<input type="radio" name="gender" value="1"/><br/> Female:<input type="radio" name="gender" value="0"/><br/> &lt;%&ndash;Favorite Food:<br/> Steak:<input type="checkbox" name="foods" value="Steak"/><br/> Pizza:<input type="checkbox" name="foods" value="Pizza"/><br/> Chicken:<input type="checkbox" name="foods" value="Chicken"/><br/>&ndash;%&gt; <textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/> Select a Level of Education:<br/> <select name="education"> <option value="Jr.High">Jr.High</option> <option value="HighSchool">HighSchool</option> <option value="College">College</option> </select><br/> Select your favorite time of day:<br/> <select size="3" name="tOfD"> <option value="Morning">Morning</option> <option value="Day">Day</option> <option value="Night">Night</option> </select> First Name:<input type="text" name="firstName" maxlength="12" size="12"/> <br/> Last Name:<input type="text" name="lastName" maxlength="36" size="12"/> <br/> Gender:<br/> Male:<input type="radio" name="gender" value="1"/><br/> Female:<input type="radio" name="gender" value="0"/><br/> &lt;%&ndash; Favorite Food:<br/> Steak:<input type="checkbox" name="foods" value="Steak"/><br/> Pizza:<input type="checkbox" name="foods" value="Pizza"/><br/> Chicken:<input type="checkbox" name="foods" value="Chicken"/><br/>&ndash;%&gt; <textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/> Select a Level of Education:<br/> <select name="education"> <option value="Jr.High">Jr.High</option> <option value="HighSchool">HighSchool</option> <option value="College">College</option> </select><br/> Select your favorite time of day:<br/> <select size="3" name="tOfD"> <option value="Morning">Morning</option> <option value="Day">Day</option> <option value="Night">Night</option> </select> <p><input type="submit"/></p> </form> View Code

e2:

<form action="" method="post"> First Name:<input type="text" name="firstName[0]" maxlength="12" size="12"/> <br/> Last Name:<input type="text" name="lastName[0]" maxlength="36" size="12"/> <br/> Gender:<br/> Male:<input type="radio" name="gender[0]" value="1"/><br/> Female:<input type="radio" name="gender[0]" value="0"/><br/> Favorite Food:<br/> Steak:<input type="checkbox" name="foods[0]" value="Steak"/><br/> Pizza:<input type="checkbox" name="foods[0]" value="Pizza"/><br/> Chicken:<input type="checkbox" name="foods[0]" value="Chicken"/><br/> <textarea wrap="physical" cols="20" name="quote[0]" rows="5">Enter your favorite quote!</textarea><br/> Select a Level of Education:<br/> <select name="education[0]"> <option value="Jr.High">Jr.High</option> <option value="HighSchool">HighSchool</option> <option value="College">College</option> </select><br/> Select your favorite time of day:<br/> <select size="3" name="tOfD[0]"> <option value="Morning">Morning</option> <option value="Day">Day</option> <option value="Night">Night</option> </select> First Name:<input type="text" name="firstName[1]" maxlength="12" size="12"/> <br/> Last Name:<input type="text" name="lastName[1]" maxlength="36" size="12"/> <br/> Gender:<br/> Male:<input type="radio" name="gender[1]" value="1"/><br/> Female:<input type="radio" name="gender[1]" value="0"/><br/> Favorite Food:<br/> Steak:<input type="checkbox" name="foods[1]" value="Steak"/><br/> Pizza:<input type="checkbox" name="foods[1]" value="Pizza"/><br/> Chicken:<input type="checkbox" name="foods[1]" value="Chicken"/><br/> <textarea wrap="physical" cols="20" name="quote[1]" rows="5">Enter your favorite quote!</textarea><br/> Select a Level of Education:<br/> <select name="education[1]"> <option value="Jr.High">Jr.High</option> <option value="HighSchool">HighSchool</option> <option value="College">College</option> </select><br/> Select your favorite time of day:<br/> <select size="3" name="tOfD[1]"> <option value="Morning">Morning</option> <option value="Day">Day</option> <option value="Night">Night</option> </select> <p><input type="submit"/></p> </form> View Code

來看經過處理後的數據:

e1:

(1)JSON.stringify($('form').serializeObject()):

{"firstName":["jack","tom"],"lastName":["aa","lily"],"foods":["Steak","Pizza","Steak"],"quote":["Enter your favorite quote!","Enter your favorite quote!"],"education":["Jr.High","Jr.High"],"tOfD":["Day","Day"],"gender":"1"}

(2)$('form').serialize():

 firstName=jack&lastName=aa&foods=Steak&foods=Pizza&quote=Enter+your+favorite+quote!&education=Jr.High&tOfD=Day&firstName=tom&lastName=lily&gender=1&foods=Steak&quote=Enter+your+favorite+quote!&education=Jr.High&tOfD=Day

說明:

第一種是無法處理的,沒辦法分清數組中的值是屬於哪個對象的。

第二種方式可以處理,但是需要編寫自定義的類型轉換器,這裡不進行說明。有興趣的童鞋,請自行探索。

e2:

(1)JSON.stringify($('form').serializeObject()):

{"firstName[0]":"aa","lastName[0]":"bb","gender[0]":"1","foods[0]":"Pizza","quote[0]":"Enter your favorite quote!","education[0]":"Jr.High","tOfD[0]":"Day",

"firstName[1]":"ds","lastName[1]":"cc","gender[1]":"1","foods[1]":["Steak","Pizza"],"quote[1]":"Enter your favorite quote!","education[1]":"Jr.High","tOfD[1]":"Day"}

(2)$('form').serialize():

firstName%5B0%5D=aa&lastName%5B0%5D=bb&gender%5B0%5D=1&foods%5B0%5D=Pizza&quote%5B0%5D=Enter+your+favorite+quote!&education%5B0%5D=Jr.High&tOfD%5B0%5D=Day&

firstName%5B1%5D=ds&lastName%5B1%5D=cc&gender%5B1%5D=1&foods%5B1%5D=Steak&foods%5B1%5D=Pizza&quote%5B1%5D=Enter+your+favorite+quote!&education%5B1%5D=Jr.High&tOfD%5B1%5D=Day

說明:

第一種看著有規律可循,貌似可以進行解析,但是不是一個標准的 JSON 格式的數據。

第二種甚至都出現了亂碼,沒有想到解析的辦法。

來看看第一種,同樣這裡提供一種思路,因為實現起來比較費勁。

思路:使用正則

like this :

Gson gson = new Gson();
String jsonInString = "{\"student[0].firstName\": \"asdf\",\"student[0].lastName\": \"sfd\",\"student[0].gender\": \"1\",\"student[0].foods\":[\"Steak\",\"Pizza\"],\"student[0].quote\": \"Enter your favorite quote!\",\"student[0].education\": \"Jr.High\",\"student[0].tOfD\": \"Day\",\"student[1].firstName\": \"sf\",\"student[1].lastName\": \"sdf\",\"student[1].gender\": \"1\",\"student[1].foods\": [\"Pizza\",\"Chicken\"],\"student[1].quote\": \"Enter your favorite quote!\",\"student[1].education\": \"Jr.High\",\"student[1].tOfD\": \"Night\"}";
String jsonWithoutArrayIndices = jsonInString.replaceAll("\\[\\d\\]", "").replaceAll("student.","");
String jsonAsCollection = "[" + jsonWithoutArrayIndices + "]";
String jsonAsValidCollection = jsonAsCollection.replaceAll(",\"student.firstName\"","},{\"student.firstName\"");
System.out.println(jsonAsValidCollection);
Student[] students = gson.fromJson(jsonAsValidCollection, Student[].class);
System.out.println("-----------------------------------------------");
System.out.println(students[0]);
System.out.println("-----------------------------------------------");

說明:

在真實的生產環境下我也沒有遇到過這樣的情況,所以這裡就不往深挖了,等什麼時候遇到這樣的情況,我再來進行補充這篇文章。

總結:

上面這部分,介紹了項目中遇到的絕大部分 SpringMVC 處理 Ajax 的問題,也提供了多種方案進行選擇,對於不常見的問題,也給出了思路。是這篇文章最重要的部分。

 

五、服務器端的 SpringMVC 如何返回 JSON 類型的字符串。

請求:

$("#testJson8").click(function () {
    $.ajax({
        url: "testReturnJsonValue",
        type: "post",
        success: function (result) {
            console.log(result);
        }
    });
});

1.返回單個對象

handler 方法:

@ResponseBody
@RequestMapping("/testReturnJsonValue")
public Person testReturnJsonValue() {
    Person person = new Person();
    person.setName("lily");
    person.setAge(23);
    return person;
}

在浏覽器控制台正常打印了 Person 對象。

注意:這裡沒有指定 dataType。

2.返回多個對象

handler 方法:

@ResponseBody
@RequestMapping("/testReturnJsonValue")
public List<Person> testReturnJsonValue() {
    List<Person> personList = new ArrayList<>();

    Person person = new Person();
    person.setName("lily");
    person.setAge(23);
    Person person2 = new Person();
    person2.setName("lucy");
    person2.setAge(33);
    personList.add(person);
    personList.add(person2);

    return personList;
}

在浏覽器控制條正常打印了 Person 數組。 

3.返回 Map

@ResponseBody
@RequestMapping("/testReturnJsonValue")
public Map<String, Person> testReturnJsonValue() {
    Map<String, Person> map = new HashMap<>();

    Person person = new Person();
    person.setName("lily");
    person.setAge(23);
    Person person2 = new Person();
    person2.setName("lucy");
    person2.setAge(33);

    map.put("1", person);
    map.put("2", person2);

    return map;
}

浏覽器控制台輸出:

 

4.在實際生產環境下的 Ajax 返回值。

封裝一個返回值類型:

/**
 * @author solverpeng
 * @create 2016-08-30-17:58
 */
public class AjaxResult implements Serializable {
    public static final String RESULT_CODE_0000 = "0000";
    public static final String RESULT_CODE_0001 = "0001";
    private String code;
    private String message;
    private Object data;

    public AjaxResult() {
    }

    public String getCode() {
        return this.code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMessage() {
        return this.message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return this.data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

 

實際使用:

@ResponseBody
@RequestMapping("/testReturnJsonValue")
public AjaxResult testReturnJsonValue() {
    AjaxResult ajaxResult = new AjaxResult();
    try {
        Map<String, Person> map = new HashMap<>();

        Person person = new Person();
        person.setName("lily");
        person.setAge(23);
        Person person2 = new Person();
        person2.setName("lucy");
        person2.setAge(33);

        map.put("1", person);
        map.put("2", person2);
        ajaxResult.setData(map);
        ajaxResult.setMessage("success!");
        ajaxResult.setCode(AjaxResult.RESULT_CODE_0000);
    } catch(Exception e) {
        e.printStackTrace();
        ajaxResult.setMessage("fail!");
        ajaxResult.setCode(AjaxResult.RESULT_CODE_0001);
    }

    return ajaxResult;
}

 

控制台打印:

六、Request Payload

(1)出現的條件:

contentType: 'application/json;charset=utf-8'

type:post

(2)具體請參看

http://xiaobaoqiu.github.io/blog/2014/09/04/form-data-vs-request-payload/

(3)建議盡量不要手動的去處理此種情況,能選用別的方式避免就盡量避免。

七、總結

本篇文章主要介紹了SpringMVC 對 Ajax 的支持,對與 Ajax 數據如何組織,重點介紹了對表單的支持。在測試的過程中也遇到過很多問題,所幸的是,也都一一克服了。還有想說的是,不可能將所有的情況都覆蓋,只是將最最常用的情況進行了分析。

也進行了另外一種序列化方式的測試,serializeArray() ,但是對我不太友好,也就沒有深入的研究。有興趣的朋友,可以自行深入研究一下。最後想說的是,寫文章不易,希望大家轉載的時候表明出處。也歡迎大家一起和我討論學習。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved