Ajax给SpringMVC传值遇到400或者415,这是由于在后台服务端定义的参数与传送的格式对应不上引起的。
格式
Ajax给java后端传值我们一般使用如下:
$.ajax({
url: "",
type: "",
dataType: "",
data: {},
success: function () { }
});
url对应后台路由的链接。get方式中 url后面可以跟拼接的参数如 /shipment/save?id=123&name=joe
type可以是post或者get。
dataType表示返回值类型,不必须 ,一般是json。
data则是我们传到后台的参数。
success是后台执行完毕后的回调函数。
第一种:contentType不设置或者application/x-www-form-urlencoded模式
示例:data参数为简单key-value参数,后台可用实体对象接收。
js代码:$.ajax({
type : "POST",
url : rootHouse + "/crm/crmElebias/getelebiasCost",
contentType : "application/x-www-form-urlencoded;charset=utf-8",
data : {
'beginTime' : firstDayOfYear,
'endTime' : endDayOfYear,
},
success : function(result) {
},
error : function(msg) {
}
});
后台controller第一种接受方式(实体对象):
@RequiresPermissions("crm:crmElebias:view")
@RequestMapping(value = "getelebiasCost")
@ResponseBody
public List<CrmElebias> getelebiasCost(CrmElebias crmElebias) {
return crmElebiasService.findList(crmElebias);
}
后台controller第儿种接受方式(字符串参数):
@RequiresPermissions("crm:crmElebias:view")
@RequestMapping(value = "getelebiasCost")
@ResponseBody
public List<CrmElebias> getelebiasCost(@RequestParam String beginTime,@RequestParam String endTime) {
return crmElebiasService.findList(crmElebias);
}
不设置contentType的情况会默认使用application/x-www-form-urlencoded模式(表单提交模式),
在表单模式中,传递的参数data:{'beginTime' : firstDayOfYear,'endTime' : endDayOfYear,}会自动转换成
参数拼接格式如下:beginTime=firstDayOfYear&endTime=endDayOfYear;
示例:data参数含数组参数,后台不能用实体对象接收,数组无法被解析为key-value形式的数据。
js:
var pointCodes= new Array(); //定义一数组
pointCodes=$('#pointCodes').val().trim().split(',');
$.ajax({
url:'/primer/bind-primer',
type:"POST",
data:{"pointCodes":pointCodes,"id":$('#primerId').val()},
success:function(res){
alert('成功');},
error:function(){
alert('服务器忙,请稍后再试'); }
});
后台controller接受参数:
@RequestMapping("/bind-primer")
@ResponseBody
public AjaxResult bindPrimer(@RequestParam(value = "pointCodes[]") String[] pointCodes,@RequestParam String id) {
return AjaxResult.resultSuccess(primerService.bindPrimer(pointCodes, id));
}
SpringMVC传递一维数组:传递数组类型时,需要在@requestParam()中添加value。
也就是@RequestParam(value = "pointCodes[]") String[] pointCodes
这里的pointCodes与 jsp中传值时的key命名一致。
第二种:contentType设置为application/json模式
data为复杂参数,可用实体对象接收
js:
$.ajax({
type:'post',
url:'${ctx}/cost/costMwh/searchlist',
data:JSON.stringify({
companyCode:"company01",
unitId_in:["3","4"],
type_in:["3","4"],
}),
dataType:'json',
contentType:'application/json;charset=utf-8',
success:function(data){
console.log(data);
}
})
后台controller接受方式(实体对象):
@RequiresPermissions("cost:costMwh:view")
@RequestMapping(value = "searchlist")
@ResponseBody
public List<CostMwh> searchlist(@RequestBody CostMwh costMwh) {
String[] aStrings=costMwh.getUnitId_in();
return costMwhService.findList(costMwh);
}
后台controller接受方式(JsonObject 对象来接收再赋值给实体):
@RequiresPermissions("cost:costMwh:view")
@RequestMapping(value = "searchlist")
@ResponseBody
public List<CostMwh> searchlist(@RequestBody JsonObject shipmentJson) {
Shipment shipment=new Shipment();
shipment.setName(shipmentJson.get("name"));
//int result = shipmentService.upsertShipment(shipment);
}
因为jQuery的ajax会默认把data:{"id":xxx,"name":xxx}这样格式的数据拼接成id=xxx&name=xxx这种以表单数据格式提交的字符串,所以application/json需要与JSON.stringify配合使用。否则会报400或者415类型不匹配。
总结:
1.不指定contentType的话,默认都是application/x-www-form-urlencoded方式发送。此时即便发送的是json格式的数据,默认情况下,jquery的ajax也会把json转为查询字符串的形式(可以通过设置processData为true或false修改),以FormData的形式发送出去。
2.如果只接收几个简单参数可以使用表单模式,复杂结构建议使用json模式。
3.指定contentType为'application/json'时候,发送的数据必须是符合json规范的字符串。通常,使用 JSON.stringify(jsondata)有较好的可读性,可以获得一个json字符串。当然,不是必须的。使用拼接的字符串,只要是符合json规范的,也是可以发送的。
比如:
data: JSON.stringify({ 'foo': 'foovalue', 'bar': 'barvalue' })
和
data: "{ 'foo': 'foovalue', 'bar': 'barvalue' }"
效果一样。
4.如果contentType为'application/json'时,发送的data不是符合json规范的字符串,则会出错。
5.如果contentType为'application/json'时,发送的data符合json规范的字符串,但后端接收参数中不是实体或jsonObject也会出错。
6.通常情况下,尽量指定contentType为'application/json',并且发送json字符串作为发送数据,这样可读性更好,并且对于复杂的接收数据类型,也能起到很好的匹配。