問題:
兩套業務邏輯代碼相同,但返回的數據不同,導致相同的前端代碼用eval解析時出錯。其中一個多了一層雙引號,分別爲
"{\"aaa\":1}" "\"{\"aaa\":1}\""
//服務端代碼
@RequestMapping(method = RequestMethod.POST, params = "method=xxx")
public
@ResponseBody
String xxx() {
Result r = service.query();
String result = JsonUtils.toJson(r);
return result;
}
//客戶端代碼
jQuery.post(url, data, function (result1) {
if (result1 != "" && result1 != null) {
var objs = eval('(' + result1 + ')');
var myResult = eval('(' + objs + ')');
}
})
解決思路:
- 比較服務端業務代碼:一致,且斷點調試return的字符串相同,都是"{\"aaa\":1}"
- 比較前端代碼:一致,且前端引擎都是velocity
- 比較http協議:不一致,request頭信息一致,但reponse頭信息不一致,返回一層雙引號的是 Content-Type:application/json;charset=UTF-8,返回兩層雙引號的是Content-type:text/html;charset=utf-8,於是懷疑有過濾器或攔截器修改了響應頭信息
- 查看過濾器和攔截器:兩邊一致,並且都沒有修改響應頭信息
- 查看spring mvc的配置的json解析工具:都是jackson,但兩個配置文件中supportedMediaTypes的順序不一致,再考慮到響應頭的不同,終於找到了問題的答案-Spring選擇Converter是有優先級的(1、請求中的ContentType和Accept對應的Converter 2、如果1無法找到對應Converter,則通過遍歷MessageConverters的canRead/canWrite選擇最有可能的Converter 3、如果2無法找到對應Converter,則返回錯誤。)
//一層引號springmvc配置的json解析
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<ref bean="mappingJacksonHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
//兩層引號springmvc配置的json解析
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<util:list id="beanList">
<ref bean="mappingJacksonHttpMessageConverter"/>
</util:list>
</property>
</bean>
解決方案
- 修改spring mvc的配置文件,調整消息轉換器的順序
- 一層引號的版本,前端去掉一層eval函數
- 優化:
- 服務端的JsonUtils.toJson()是多餘的,因爲spring mvc配置的json解析工具會自動序列化結果。
- text/html;charset=UTF-8這種Content-Type會在數據外層包裹上一層雙引號,如果返回的是string類型,則會出現兩層雙引號;返回Object,也會出現一層雙引號,需要用eval來去除,或者在jQuery post() 方法指定預期的服務器響應的數據類型爲'json';
//服務端代碼
@RequestMapping(method = RequestMethod.POST, params = "method=xxx")
public
@ResponseBody
Object xxx() {
Result r = service.query();
Return r;
}
//1、客戶端代碼(如果響應頭是application/json;charset=UTF-8)
jQuery.post(url, data, function (result1) {
if (result1 != "" && result1 != null) {
var myResult = result1;
}
})
//2、1 客戶端代碼(如果響應頭是text/html;charset=UTF-8)
jQuery.post(url, data, function (result1) {
if (result1 != "" && result1 != null) {
var myResult = result1;
}
},'json')
//2、2 客戶端代碼(如果響應頭是text/html;charset=UTF-8)
jQuery.post(url, data, function (result1) {
if (result1 != "" && result1 != null) {
var myResult = eval('(' + result1+ ')');
}
})