SpringMVC——对Ajax的处理(包含 JSON 类型)
一、首先要搞明白的一些事情。
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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';} }
(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;}@Overridepublic String toString() {return "Student{" +"firstName='" + firstName + '\'' +", lastName='" + lastName + '\'' +", gender=" + gender +", foods=" + foods +", quote='" + quote + '\'' +", education='" + education + '\'' +", tOfD='" + tOfD + '\'' +'}';} }
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;}}
后端处理:
@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"e=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>{@Overridepublic Student convert(String source) {return InjectUtil.convert2Obj(source, Student.class);} }
这里我编写了一个通用的类型转换器:
用来转换形如:
firstName=jack&lastName=lily&gender=1&foods=Steak&foods=Pizza"e=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/><%–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> <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/><%– 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> </form>
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/><%–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>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>
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>
来看经过处理后的数据:
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"e=Enter+your+favorite+quote!&education=Jr.High&tOfD=Day&firstName=tom&lastName=lily&gender=1&foods=Steak"e=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"}
{"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"e%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"e%5B1%5D=Enter+your+favorite+quote!&education%5B1%5D=Jr.High&tOfD%5B1%5D=Day
firstName%5B0%5D=aa&lastName%5B0%5D=bb&gender%5B0%5D=1&foods%5B0%5D=Pizza"e%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"e%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() ,但是对我不太友好,也就没有深入的研究。有兴趣的朋友,可以自行深入研究一下。最后想说的是,写文章不易,希望大家转载的时候表明出处。也欢迎大家一起和我讨论学习。
SpringMVC——对Ajax的处理(包含 JSON 类型)相关推荐
- 通过Ajax进行POST提交JSON类型的数据到SpringMVC Controller的方法
现在在做的项目用到了SpringMVC框架,需要从前端angular接收请求的JSON数据,为了测试方便,所以直接先用AJAX进行测试,不过刚开始用平时用的ajax方法,提交请求会出现415或者400 ...
- SpringMVC接收ajax请求并回传json数据,配置的步骤及问题解决。No converter found for type ArrayList with Content-Type null
1. 在maven项目的pom.xml文件引入依赖 <dependency><groupId>com.fasterxml.jackson.core</groupId> ...
- json mysql 字段 默认值_MySQL中的JSON类型
前言(废话) 昨天抽了点时间在网上搜列了一个开源项目,项目挺完整的,前后台分离还带有微信小程序,我Clone下代码,经过一番倒腾,嘿~还真就跑起来了.在这个过程中,体验了一把VUE项目工程细节,因为之 ...
- SpringMVC—对Ajax的处理(含 JSON 类型)(2)
这里编写了一个通用的类型转换器:用来转换形如: firstName=jack&lastName=lily&gender=1&foods=Steak&foods=Pizz ...
- SpringMVC——对Ajax的处理(包含 JSON )
一.首先要搞明白的一些事情. 1.从客户端来看,需要搞明白: (1)要发送什么样格式的 JSON 数据才能被服务器端的 SpringMVC 很便捷的处理,怎么才能让我们写更少的代码,如何做好 JSON ...
- SpringMVC绑定ajax传递json数据到pojo对象错误(400 Bad Request)
问题如标题所述,ajax向SpringMVC Controller传递JSON数据,遇到了错误"Failed to load resource: the server responded w ...
- springmvc全局异常处理ControllerAdvice区分返回响应类型是页面还是JSON
springmvc全局异常处理ControllerAdvice区分返回响应类型是页面还是JSON 参考文章: (1)springmvc全局异常处理ControllerAdvice区分返回响应类型是页面 ...
- 【MyBatis】foreach实现postgresql的json类型数据的集合包含遍历查询
目录 需求描述 解决思路 运行结果 需求描述 如下图所示,sub_rule表的detail字段是json类型的(数据库采用的是postgresql),里面存的是预先定义好的规则,例如某规则是{&quo ...
- springmvc中ajax,springmvc中ajax处理
1.使用HttpServletResponse处理--不需要配置解析器 @Controller public class AjaxController { @RequestMapping(" ...
最新文章
- 在织梦模板中不适用ajax,直接用标签也能调用当前会员的信息
- 实战SSM_O2O商铺_12【商铺注册】View层之前台页面
- 前端工程师必备:学习资源全网罗
- linux ctime 时间戳,Linux时间戳atime ctime mtime区别及相关命令
- COM_PRODUCT_READ_SINGLE called by composite API when line item is deleted
- [MEGA DEAL]完整的Java编程训练营(94%折扣)
- oracle数据库集群日志,Oracle集群数据库中恢复归档日志
- python 问题集
- python读取大文件的坑_Python读取大文件的坑“与内存占用检测
- JS-JavaScript打开新页面的两种方式:当前页面打开和新页面打开
- 毕业论文可能用到的一些东西
- nRF Sniffer抓包环境搭建
- python类和属性的应用搬家具
- 聚焦扶贫,爱在瑶山,深圳市华南物流商会在行动
- python招聘现状-python招聘现状
- 《自然语言处理学习之路》05 新闻分类任务实战
- python 用QQ邮箱发送邮件
- 电子商务格局下的营销未来
- 什么是云仓一件代发?电商物流云仓,新疆云仓
- 从贪心算法到暴力递归法——从局部最优到整体最优
热门文章
- js字符串常用方法:chartAt、charCodeAt、toUpperCase、toLowerCase、substr、substring、slice、replace、lastIndexof等
- YOLOv5添加自定义数据增广方法
- 中达优控宏编译失败处理方法
- Windows滑动关机方法
- 爱一个不爱你的人,就像在机场等一艘船
- 2021华为9.1秋招机试
- 界面控件DevExpress WinForms的数据网格,让业务数据管理更轻松!
- icmp_seq=1 Destination Host Unreachable
- html字体自动换颜色代码,css怎么给字体换颜色?
- java sinh_Java StrictMath sinh()用法及代码示例