这段时间,在给一个地区门户网站(alexa全球排行1200左右)做SSO集成,其中的一个部分就是Web Services服务接口,以及客户端,我们采用的是REST方式,不是SOAP,大致就是客户端通过HTTP POST方式向服务器提交数据,如账号同步,服务器返回xml,给客户端反馈。但提交过程中中文问题出来了,因为账号中有个realName字段是中文。客户端有以下几种:
1、Java HTTP客户端(HttpURLConnection)
2、PHP客户端(curl库)
3、ajax 客户端(XMLHTTP)
4、普通表单提交(POST方式)
…..
开发上面四种客户端API和 demo都很快,现在就记录一下中文解决方案问题吧。
我之所以要发表出来,是因为我这儿的解决方式是自动化的,编码量最小,并且我进行了无数次尝试,确定怎样行,怎样不行,并找出原因。
注意:我只是说明了request的中文解决方案,并且只是POST方式,但只要是对这个很理解,response的中文也就很简单了。
开始时候,我也是采用了比较机械的,在服务器端servlet中将得到的参数值:
[code]byte[] b = value.getBytes("ISO-8859-1");
output = new String(b,"UTF-8");[/code]
这样可以解决问题,而且都成功了,但必须在四种客户端发送的中文时候要进行encoding操作。最后我觉得这肯定不是最优解,因为工作量太大,于是决定重构。
将发往服务器的request都用filter拦截,主要就是下面这句话,其实这个方式非常old了,不值得一提。在doFilter里:
[code]request.setCharacterEncoding(encoding); [/code]
也就是将到来的所有请求(还没有说到response呢)都用指定的编码(UTF-8)进行编码。
用filter,可以解决服务器移植的问题,如我最熟悉的Tomcat,resin,WL,WS。
我用axis (著名的Web Services SOAP引擎)附带的TCPMonitor来探测发出的POST请求。
[b]Java HTTP客户端(HttpURLConnection):[/b]
必须将请求数据的key/value的value,进行编码:[code]URLEncoder.encode(value,"UTF-8")[/code];
[b]PHP客户端(curl库):[/b]
同上,必须进行转码:
[code]$truename = iconv("GBK", "UTF-8","陈志武");[/code]
因为我们PHP默认环境是中文
[b]ajax客户端:[/b]
发送POST请求时,直接用中文,不需要用Javascript的encodeURI(),或者escape(),但是用了也不影响。
why?因为ajax POST方式默认是以UTF-8方式发送的。对已经编码的中文,也就是一些%E9%99%88%E5%BF%97%E6%AD%A6这样的正常符号了,服务器就忽略编码了,因为编和不编一个样。
注意,这两个函数对中文encode后结果不一样。用encodeURI()是以UTF-8编码,但没有其它编码类型可选择,这样,如果你的服务器端的filter用GBK默认,那么,就不能象这样自动处理。
所以,用ajax客户端时,必须慎重点。
[b]普通表单提交(POST方式)[/b]
如果希望自动解决问题,在filter里对request请求编码设置为UTF-8的前提下,最好就是加入如下:
[code]<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />[/code]
如果charset为GBK,那么到Server端就是乱码的。
why?因为,用submit方式提交时,我们的提交的表单编码类型(enctype)是:
Content-Type: application/x-www-form-urlencoded,也就是说,提交的时候,我们的中文会自动进行编码,但依据就是上面的那个html指令。这个证据可以从TCPMonitor拦截的HTTP数据包里看到。
和上面的方式比较,ajax方式感觉是浏览器为我们建立了一个http通道,直接将中文提交上去了,和最前面介绍的两种一样。
在服务器端,我们的Java Web容器或应用服务器会自动给我们的request参数解码。将编码后的字符还原为本来面目。
如果你在控制台里面看到的都是正确的中文,你就可以抛开数据库这个存在编码问题了,但那个有时也有点麻烦。
1、Java HTTP客户端(HttpURLConnection)
2、PHP客户端(curl库)
3、ajax 客户端(XMLHTTP)
4、普通表单提交(POST方式)
…..
开发上面四种客户端API和 demo都很快,现在就记录一下中文解决方案问题吧。
我之所以要发表出来,是因为我这儿的解决方式是自动化的,编码量最小,并且我进行了无数次尝试,确定怎样行,怎样不行,并找出原因。
注意:我只是说明了request的中文解决方案,并且只是POST方式,但只要是对这个很理解,response的中文也就很简单了。
开始时候,我也是采用了比较机械的,在服务器端servlet中将得到的参数值:
[code]byte[] b = value.getBytes("ISO-8859-1");
output = new String(b,"UTF-8");[/code]
这样可以解决问题,而且都成功了,但必须在四种客户端发送的中文时候要进行encoding操作。最后我觉得这肯定不是最优解,因为工作量太大,于是决定重构。
将发往服务器的request都用filter拦截,主要就是下面这句话,其实这个方式非常old了,不值得一提。在doFilter里:
[code]request.setCharacterEncoding(encoding); [/code]
也就是将到来的所有请求(还没有说到response呢)都用指定的编码(UTF-8)进行编码。
用filter,可以解决服务器移植的问题,如我最熟悉的Tomcat,resin,WL,WS。
我用axis (著名的Web Services SOAP引擎)附带的TCPMonitor来探测发出的POST请求。
[b]Java HTTP客户端(HttpURLConnection):[/b]
必须将请求数据的key/value的value,进行编码:[code]URLEncoder.encode(value,"UTF-8")[/code];
[b]PHP客户端(curl库):[/b]
同上,必须进行转码:
[code]$truename = iconv("GBK", "UTF-8","陈志武");[/code]
因为我们PHP默认环境是中文
[b]ajax客户端:[/b]
发送POST请求时,直接用中文,不需要用Javascript的encodeURI(),或者escape(),但是用了也不影响。
why?因为ajax POST方式默认是以UTF-8方式发送的。对已经编码的中文,也就是一些%E9%99%88%E5%BF%97%E6%AD%A6这样的正常符号了,服务器就忽略编码了,因为编和不编一个样。
注意,这两个函数对中文encode后结果不一样。用encodeURI()是以UTF-8编码,但没有其它编码类型可选择,这样,如果你的服务器端的filter用GBK默认,那么,就不能象这样自动处理。
所以,用ajax客户端时,必须慎重点。
[b]普通表单提交(POST方式)[/b]
如果希望自动解决问题,在filter里对request请求编码设置为UTF-8的前提下,最好就是加入如下:
[code]<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />[/code]
如果charset为GBK,那么到Server端就是乱码的。
why?因为,用submit方式提交时,我们的提交的表单编码类型(enctype)是:
Content-Type: application/x-www-form-urlencoded,也就是说,提交的时候,我们的中文会自动进行编码,但依据就是上面的那个html指令。这个证据可以从TCPMonitor拦截的HTTP数据包里看到。
和上面的方式比较,ajax方式感觉是浏览器为我们建立了一个http通道,直接将中文提交上去了,和最前面介绍的两种一样。
在服务器端,我们的Java Web容器或应用服务器会自动给我们的request参数解码。将编码后的字符还原为本来面目。
如果你在控制台里面看到的都是正确的中文,你就可以抛开数据库这个存在编码问题了,但那个有时也有点麻烦。