我们的架构是b/s的,后台用的是tomcat,和google的webservice打交道还用到一个gae做代理。
之前的博文我们说过在tomcat和浏览器之间的ajax交互时要用一种客户端encode两次加上一个辅助函数加工然后服务端decode两次的恶心解决方案。后来我们研究了一下tomcat,发现其实问题是这样的。
tomcat默认使用iso-8859-1来解释request的,所以我们用ff提交参数时用的是utf8,我们在浏览器里输入“大学”,其实是被ff encode过的(被转成%B5%33形式),传到服务器时tomcat又用iso-8859-1 decode了。所以我们想到解决方案如下
String keyword =URLEncoder.encode(request.getParameter("keyword"),"ISO-8859-1");
keyword=URLDecoder.decode(keyword, "UTF-8");
这样子我们反过来弄一下就ok了。
这里还要说一下,如果换成时ie的话,默认“大学”这个url参数会用gbk,如果还是用上面的那个,其实就会出现乱码。这里还要说glassfish貌似也是用的iso-8859-1
这里还要讲一个关于HTTPURLConnection的事情,我们在tomcat用HTTPURLConnection时,我在设置parameter的时候没有encode我的参数,我就这样传过去了,而在本地的jetty服务器的gae上接收到了我的字符串竟然是对的,看来HttpURLConnection会自动帮我们按照默认的charset(linux下是utf8)把字符串编码再传过去。然后再我们本地的gae上,可以直接写这样的code
String keyword = req.getParameter("keyword");
String center = req.getParameter("center");
String range = req.getParameter("range");
这个可能gae用的jetty服务器又自动帮我们decode了,这里虽然我们没有decode和encode,但是程序都自动帮我们完成了。但是必须满足客户端和服务器用的默认的编码是一样的。
这里讲一下什么是decode什么是encode,比如,我们对一个“作者”encode,这里会encode成 %E4%BD%9C%E8%80%85这样的,再encode一下会,encode成“%25E4%25BD%259C%25E8%2580%2585”这样,%会转成%25。 而decode呢?如果我们对“%25E4%25BD%259C%25E8%2580%2585” decode会变成“%E4%BD%9C%E8%80%85”,而对“%25E4%25BD%259C%25E8%2580%2585大学” decode会变成“%E4%BD%9C%E8%80%85大学”,也就是说decode可能只会对%开头的东西进行decode。而encode比较诡异,处理%的手段让人搞不懂。
话说回来,我做了几次实验,我发现URLConnection会自动帮助我们进行编码的,而且很智能,如果我们事先encode过,他就不会再帮我们encode。而本地gae会用默认的utf8方式编码。设想一个情况,我们用gbk encode参数然后再传到gae上,我们就需要在gae上先encode("UTF-8")在decode 成gbk。这里的道理是一样的。而我们可以用一个函数就是request.setCharsetEncoding("GBK")来直接来让服务器帮我们用GBK转,这样就不要先encode再decode了。
现在我们看age里面的代码,我们需要请求google的web service。这时,我们仍然是需要用HTTPURLConnection这个类,但是我们在没有encode参数的时候,发给google api时竟然说url是不合法的,一定要实现encode才可以。这就不懂了,为什么一定要我们手动encode呢,不是HTTPURLConnection自动帮我们encode了吗?我想这是不是同一个版本的URLCOnnection啊?我看了一下原来不加encode的错误堆栈信息,原来最后会调用一个什么httpclient的类,而这个类不是标准库里的,是外部的,也不知道这里面到底出了什么鬼!!!就连我step into进去HTTPURLConnection,里面的堆栈也是不一样的,诡异啊!!!
接着我们从webservice里获得了json字符串,里面也还是没有decode过的utf8,随即
String allString=URLDecoder.decode(all.toString(),"UTF-8");
最后还要返回给tomcat结果,此时如果我们不用以下这个字符编码限定会出问题
resp.setContentType("text/json");
resp.setCharacterEncoding("UTF-8");
PrintWriter writer=resp.getWriter();
我不知道这个是为什么!我看本地的age上默认是utf8啊,难道传过来的时候就不是utf8?
后来我又搞成这样子,在本地gae上这样写
OutputStream writer = resp.getOutputStream();
writer.write(jsonString.getBytes());
writer.close();
在tomcat上这样写
byte[] bytes=new byte[10000];
InputStream inputStream=connection.getInputStream();
inputStream.read(bytes);
String string=new String(bytes);
这样我们用纯字节进行传递就不可能会有错了!!!这里我没有指定到底用什么编码传递,这个时候会用默认的,我始linux的,所以java的默认编码用utf8。
我们把age部署到服务器,在服务器上出现了诡异,原来服务器上用的是一个us什么的默认编码格式。真正的age要想正常返回给我们字符串,需要加上这么一句话
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));
StringBuilder all = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
all.append(line);
}
在我本地gae是不需要加第一句话中的UTF-8的。因为在服务器上的gae是us编码的,所以需要这么转,否则默认就转成us这种东西了。
这里就又有一个问题了,service传过来的是一个需要decode的东西,我在本地的gae上用
new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));
得到的字符串是需要再一次decode的,而在服务器上的gae是不需要再一次被decode的。
终其所述,无论本地还是服务器的age下的HTTPURLConnection和普通java的不一样,它不会帮我们encode;而服务器上gae的InputStreamReader和本地的gae和普通java也不一样,他会自动转码。
分享到:
相关推荐
Google Map API 使用示例
详尽的介绍了google map api 并简单的举了几个例子,能帮助你了解Google map 编程
谷歌地图Google Map API中文开发文档 V3
google map api 实现自定义mark和其移动
google map api 参考文档google map api 参考文档google map api 参考文档google map api 参考文档google map api 参考文档google map api 参考文档
写了一些GOOGLE MAP应用,大家分享
费了半天才找到的源代码,很好用的,如果想学习google map api二次开发,他会提供很好帮助!
GoogleMap api 中文 GoogleMap api 中文 GoogleMap api 中文 GoogleMap api 中文 GoogleMap api 中文
谷歌地图api v3 学习文档,资料查询, 基础学习。
这个swc是googlemap对flash的api,他并不适用于flex,关于flex,有自己的swc哦
Android google map API例子
最新的Google Map Api 帮助文档 免费下载地址: http://www.hkmci.com
包含了利用Google Map API进行二次开发的很多实例,为刚开始接触Google Map API进行二次开发的读者提供了一条捷径。
google map api 调用的实例,
基于Google map 的API,带搜索功能
Google Map api V3 (3.9.12)的离线开发包
GOOGLE MAP api 7个案例。 CurrentAddress 得到当前位置 gMap 地形 路线 GoogleMapDemo 当前位置 MAP 绘制路线 MapView 放大缩小 WeatherMap 在MAP上添加图片 WorldCities 城市经纬度的切换 以及 动画切换效果
使用google地图的反向地址解析功能,提供一个经纬度得到对应地址,或者给出模糊地址,得到经纬度,放在java后台代码中处理,这个使用的是Google的地理编码服务。一般而言数据量不大的情况使用是不限制的。按照Google...
优秀的Google Map API基本源码,值得学习!
基于googlemap api 的gps终端和用户管理系统基于googlemap api 的gps终端和用户管理系统基于googlemap api 的gps终端和用户管理系统基于googlemap api 的gps终端和用户管理系统基于googlemap api 的gps终端和用户...