今天公司测试发现在IE9以下浏览器,程序好多功能点返回的JSON都是提示下载。
开发环境和框架: springboot(springMVC+mybatis) 前端:jquery easyui
看了下后端代码,controller里面基本都是声明返回的数据格式为MediaType.APPLICATION_JSON,如下:
@ResponseBody
@RequestMapping(value = "/sysnotice/validate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON)
public String validateEdit(@Param("noticeId") int noticeId, HttpSession session) {
//....
}
搜了一些文章说IE10以下不支持直接返回的content-type为json。但是我看了下其他同事的一些代码,又是可以支持的。
比如以下的jquery.ajax方式请求是可以支持的,代码如下:
$.ajax({
type : 'post',
url : '${path}/sysnotice/validate?noticeId=' + noticeId,
contentType : 'application/json',
dataType : 'json',
success : function(result) {
//var result = eval('(' + result + ')');
if (result.success) {
addTabs("通知公告编辑", "${path}/sysnotice/toEdit?noticeId=" + noticeId);
} else {
$.messager.alert('系统提示', result.msg, 'error');
}
}
});
但是如果使用jquery.form提交表单的又不支持,返回的json数据,在IE10以下浏览器提示下载,代码如下:
$('#fm').form('submit', {
url : '${path}/sysnotice/update',
dataType : 'json',
onSubmit : function() {
var isValid = $(this).form('validate');
if (!isValid) {
$.messager.progress('close'); // 当表单无效时隐藏进度条
}
return isValid; // 返回false将停止表单的提交操作
},
success : function(result) {
$.messager.progress('close'); // 当表单提交成功时隐藏进度条
//var result = eval('(' + result + ')');
var result = JSON.parse(result);
if (result.success) {
$.messager.show({ //右下角出现提示框
title : "系统提示",
msg : result.msg
});
closeWindow();
} else {
$.messager.alert('系统提示', result.msg, 'error');
}
}
});
2种方式,为什么上面使用Jquery.ajax方式IE10以下浏览器可以支持,使用jquery.form插件提交表单的就无法支持呢? 有知道的小伙伴可以给我留言哈。
为了解决这个IE10以下浏览器提示下载JSON数据问题。
1. 修改XML配置文件,增加输出数据格式 text/html; chartset=utf-8
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- 将StringHttpMessageConverter的默认编码设为UTF-8 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" />
<property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
</bean>
<!-- 将Jackson2HttpMessageConverter的默认格式化输出设为true -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="prettyPrint" value="true"/>
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value> <!-- 避免IE出现下载JSON文件的情况 -->
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
2. 修改controller方法,修改produces为MediaTypes.TEXT_HTML_UTF_8,(其实步骤1已经做了配置,这里可不设置返回的数据格式。)
@ResponseBody
@RequestMapping(value = "/sysnotice/update", method = RequestMethod.POST, produces = MediaTypes.TEXT_HTML_UTF_8)
public ResultModel update(HttpSession session, SysNotice notice) {
至此,IE10以下版本提示下载JSON的问题已经得到解决,但是这里又引出一个新的问题:
部署到服务器上后发现,这些修改的过的编辑,新增功能访问速度都非常慢,要等待20几秒才会有结果返回,并且返回的JSON数据返回乱码(真的很诡异,其他功能都是好的,就今天改IE10以下下载JSON问题的相关功能出了问题)。于是一顿排查访问慢的问题,花了很多时间还是没有找到问题,最后终于把怀疑的对象转移到乱码问题上(因为一开始我根本不关注这个乱码问题,在我看来乱码问题怎么可能引起访问问题慢,所以我一开始就疏忽了,想等解决了访问慢问题后再回头过来修改乱码问题)。
浏览器接收到的返回JSON如下:
尝试了下,设置返回的内容为全英文,居然访问速度飞快了。(这里完全不理解为什么乱码问题导致访问速度奇慢,有了解的小伙伴留言给我哈,感激不尽。)
@ResponseBody
@RequestMapping(value = "/sysnotice/update", method = RequestMethod.POST, produces = MediaTypes.TEXT_HTML_UTF_8)
public ResultModel update(HttpSession session, SysNotice notice) {
try {
long start = System.currentTimeMillis();
sysNoticeService.editSysNotice(notice);
long end = System.currentTimeMillis();
ResultModel rm = ResultModel.success("修改成功"); //我只要把这几个汉字修改英文,访问速度飞快
System.out.println("返回msg为:" + rm.getMsg());
System.out.println("花费的时间是: ======================================><" + DateUtil.getDatePoor(end-start));
return rm;
} catch (Exception e) {
e.printStackTrace();
return ResultModel.error("修改失败");
}
}
于是解决问题的思路就很清晰了,那就是解决乱码问题。于是又花了很多时间解决乱码问题,各种方式尝试,不过悲剧的是居然都无法解决问题。也上网搜了很多解决办法,不过搜出来的结果基本都是一样的,基本都是在以下几个地方不停调整:
1). 设置方法的返回的数据格式: produces = MediaTypes.TEXT_HTML_UTF_8
2). 设置springmvc配置文件,设置StringHttpMessageConverter,MappingJackson2HttpMessageConverter等等返回数据格式和编码为text/html;charset=UTF-8
3). <mvc:annotation-driven>配置要放在<context:component-scan>前面等等
但是网上搜索的解决办法,都不能解决我的乱码问题,如下所示,我SpringMVC的配置文件都调成这鬼样子了,还是解决不了乱码问题。
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- 将StringHttpMessageConverter的默认编码设为UTF-8 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" />
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value> <!-- 避免IE出现下载JSON文件的情况 -->
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 将Jackson2HttpMessageConverter的默认格式化输出设为true -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="prettyPrint" value="true"/>
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value> <!-- 避免IE出现下载JSON文件的情况 -->
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 配置bean的注解配置的扫描的包路径,spring mvc的controller层建议用注解配置 -->
<context:component-scan base-package="com.mycom"/>
最后静下心来认真思考,发现,在我本地测试根本不存在乱码问题(访问速度也是很溜)。那么只能从系统环境,应用服务器环境上去找问题了。
一步步来排除问题:
1. 本地开发环境使用springboot,jetty启动应用服务,不存在乱码问题,访问速度也没问题
2. 本地环境使用eclipse集成tomcat部署应用,一样不存在乱码问题,访问速度也没问题
3. 将步骤2中生成的war包(F:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps里面的war包)直接复制到本地tomcat服务器webapps目录下,启动tomcat服务器,出现了乱码问题,访问速度很慢
看来是tomcat应用服务器设置问题了,于是又继续网上搜索tomcat服务乱码相关问题,搜出来的结果基本都是差不多的。
(1).修改server.xml中,设置URIEncoding='UTF-8',这个应该跟我的问题没什么关系,抱着试一试的心态,试了下,果然不能解决我的问题
(2).修改tomcat启动参数,catalina.bat文件中增加编码设置:JAVA_OPTS=-Dfile.encoding=UTF-8 ,居然解决了我的问题。
下一步要做的是: 了解这个JAVA_OPTS=-Dfile.encoding=UTF-8 参数的作用了:
不同环境下打印: System.out.println(System.getProperty("file.encoding"));
发现在jetty和eclipse集成tomcat中,打印出来的是utf-8(有大神分析说,eclipse启动tomcat会使用项目的text file encoding作为启动编码,一般我们eclipse项目都习惯设置为utf-8)。
在单独启动的tomcat中打印出来的是GBK, 加入JAVA_OPTS=-Dfile.encoding=UTF-8设置后打印出来的是:utf-8.
虽然暂时解决了问题,但是还有很多不解的地方。JAVA_OPTS=-Dfile.encoding=UTF-8,这个我基本没设置过,这还是第一次主动去设置tomcat启动参数,以前也没发现出现乱码问题,为什么这次就莫名的出现了呢?