Java httpclient解决方案中的中文传递
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java httpclient解决方案中的中文传递(2009-03-05 17:21:33)
标签:杂谈
1 Commons HttpClient 开源项目简介
Http 协议是一种应用十分广泛的网络应用层协议。在Java 网络编程中我们会经常碰到Http 协议编程, 虽然JDK 提供了
HttpURLConnection 编程接口对Http 协议进行支持, 但是由于协议应用本身
的复杂性, 使得在大量实际项目单纯使用JDK 进行Http编程仍然相对比较困难。针对这种情况, 开源软件组织Apach 推出了HttpClient 开源组件, 并且提供稳定持续的升级版本, 因此在实际项目中采用HttpClient 组件进行Http 协议编程是一种高效经济的解决方案。
2 Commons HttpClient 中文环境下编程常见问题
由于HttpClient 组件设计的高度灵活性及易用性, 应用HttpClient 组件进行编程本身并不复杂。但是由于Java 编程环境自身容易出现字符编码问题, 衍生于Java 语言并主要由英语语系国家技术人员推出的HttpClient 组件自然在中文环境中会存在一定的编码问题, 同时由于部分Web 浏览器及Web 服务器并未严格实现标准Http 协议规范, 使得比较严格遵循标准Http 协议规范的
Http-Client 组件在与部分浏览器及服务器进行交互时会出现少量兼容性问题。笔者在中文环境下用HttpClinet 开发校外资源访问系统的过程中碰到系列HttpClient 技术问题, 经过测试查证找到相应的解决办法, 这对解决HttpClient 编程问题, 特别是中文环境下Http-Client 编程具有较大的借鉴
作用。( 注: 本文编程的HttpClient 组件版本为: Release 3.1 Beta 1)
3 Commons HttpClient 编程的典型问题及解决办法
3.1 URL 中文参数无法识别的问题
通常情况在Commons HttpClient 编程中我们用下列语句就可以向一个目标服务器提交一个Web 请求:
HttpClient client=new HttpClient();
GetMethod method = new GetMethod (url);//本示例使用Get 方法, 当然也可使用Post 方法PostMethod method//=new PostMethod(url);
client.executeMethod(method);
InputStream receiver=method.getResponseBodyAsStream();
如果URL 没有中文参数,以上语句执行起来没有任何问题,但是如果URL 中含有中文字符,中文参数将无法被Web 服务器识别, 程序虽然可以正常运行, 但却
无法得到正确结果。同时返回的Http 响应头, 如果含有中文字符也将出现乱码。分析源码发现, 这是HttpClient 中的HttpElementCharset 参数( 创建HTTP headers 的字符集) 的默认值为US- ASCII, ContentCharset 参数( 创建contentbody 的字符集) 的默认值为ISO- 8859- 1 的原故, 因此需要使用下列语句改变这些参数的默认值:
client = new HttpClient();
params=client.getParams();
params.setHttpElementCharset("GBK");
params.setContentCharset("GBK");
或者使用:
method.getParams().setHttpElementCharset("GBK");
method.getParams().setCredentialCharset("GBK");
method.getParams().setContentCharset("GBK");
第一种方式可能会更好, 它在HttpClient 初始化时就对字符默认参数进行了
设置, 作用范围更广。第二种方式仅对使用具体的请求方法时起作用, 字符集的作用范围有限。一般情况下我们用上述语句即可实现中文字符的正确识别。但要深入使用我们会发现如果URL 中文参数含有中文特殊字符(如“{”, “}”等符号), 程序将抛出URIException 异常,导致请求无法完成。继续研究HttpClient 的源代码发现, URI 类是负责解析URL 的核心类, 控制URL 编码字符集是ProtocolCharset 参数, 默认情况下为UTF- 8 编码, 同时还在URI 的构造函数提供了一个逻辑值来决定是否过滤非法字符, 而恰恰一些中文特殊字符也被当成非法的字符过滤掉了, 根据产生问题的原因, 我们在基本解决中文编码问题的基础上结合以下容错的方法来最终保证中文编码的正确识别:
String url=⋯.;
try
{strUri=new URI(uri,true,"GBK");}
catch(URIException e)
{strUri=new URI(uri,false,"GBK");}
method.setURI(strUri);
经测试上述办法解决大量的已知URL 中文参数不能识别的问题, 当然如果在程序个别地方上述方法依然不能奏效, 你还可以使用Java 中文编码转换的基础
解决方法, 借助ISO- 8859- 1 标准编码过渡, 能够轻易将JVM在网络传送过程转换成的UTF8 编码还原成GBK 编码, 下面的代码实现了这一功能:
byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP 流中取"NAME"的UTF8 数据
b = utf8_value.getBytes("8859_1"); //中间用ISO- 8859- 1 过渡
String name = new String(b, "GB2312"); //转换成GB2312 字符
3.2 URL 中的%问题
部分不太规范的中文网站中使用%作URL 中参数的一部分传递给服务器, 而中
文Windows 中的许多主流浏览器也兼容这一例外。事实上%是作为Http 协议中的UrlEncode 编码的保留字符不能直接在URL 中使用, 必须被转义成%25 这样的形式, 事实上HttpClient 就会自动将字符%转化成%25。正是这种原因当HttpClient 截获IE 浏览器的请求并将其转发到服务器时, 将会导致查询参数错误。分析HttpClient 的源码发现, 这一转化是在URI 类中实现的, 经反复测试未能找到一种通过HttpClient 公开接口实现这一兼容性的方法。目前只能采取修改URI 类源码重新编译的办法来实现:
public static final BitSet allowed_query = new BitSet(256);
// Static initializer for allowed_query
static {
allowed_query.or(uric);
allowed_query.clear('%');将源码中此语句去掉或注释即可}
3.3 Cookie 整合问题