一、现象描述
前端 ajax 方式调用 springmvc 接口时,返回 415 (Unsupported Media Type) 错误:
前端代码:
function fSave(url) {
var obj = {};
obj['cateId'] = $("input[name=cateId]").val();
obj['cateName'] = $("input[name=cateName]").val();
$.ajax({
url: url,
method: 'post',
data: JSON.stringify(obj), // 以json字符串方式传递
success: function(data) {
console.log(data);
},
error: function(data) {
console.log("error...");
console.log(data);
}
});
}
接口代码:
@RequestMapping(value = "/save-by-model-2", method = RequestMethod.POST)
@ResponseBody
public Category saveByModel2(@RequestBody Category category) {
return category;
}
Category 类定义:
package com.wlm.test.category;
/**
* 分类实体类对象
*
* @author wengliemiao
*/
public class Category {
private int cateId = 0;
private String cateName = "";
// getter(), setter()...
}
二、出错原因
经过对 SpringMVC 中 HTTP 请求响应机制源码(SpringMVC 中 HTTP 请求与响应原理)的深入研究,发现 SpringMVC 解析输入参数和返回数据时,会分别调用相应的输入参数解析类: HandlerMethodArgumentResolver
、返回值处理类 HandlerMethodReturnValueHandler
对数据进行处理。
本实例中,错误为对输入参数进行解析出错,即调用 HandlerMethodArgumentResolver.resolveArgument()
方法时出错。而 @ResponseBody 对应的输入参数解析器为 RequestResponseBodyMethodProcessor
, 该方法中调用了readWithMessageConverters()
方法,调用具体的 HttpMessageConverter.read()
方法对输入参数进行解析。
本次实例中的消息转换器类 HttpMessageConverter
有:
而具体调用哪个 HttpMessageConverter
类则根据具体的 HttpMessageConverter
类是否能对相应的媒体类型 MediaType
读或写来判断。接口定义如下:
如果无匹配的 HttpMessageConverter
类存在,则抛出 HttpMediaTypeNotSupportedException
异常:
而在 ajax post 访问中,如未显示指定 contentType
的值,则默认为表单类型
application/x-www-form-urlencoded; charset=UTF-8
。而在 springmvc 中,并无对
application/x-www-form-urlencoded; charset=UTF-8
进行处理的
HttpMessageConverter
类,因此抛出异常。
ajax get 方式编码参考: JavaWeb编码之get方式中文乱码问题
三、解决方案
根据第二点的原理介绍,只需指定接口返回的字符集,且 springmvc 支持,即可解决中文乱码问题,
如:
$.ajax({
url: url,
method: 'post',
contentType: 'application/json',
data: JSON.stringify(obj), // 以json字符串方式传递
success: function(data) {
console.log(data);
},
error: function(data) {
console.log("error...");
console.log(data);
}
});
输出为: