浙江省高等学校教师教育理论培训

微信搜索“教师资格证岗前培训”小程序

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

HTTPCLIENT 解决乱码方案 - linfeng_0212的日志 - 网易博客

HTTPCLIENT 解决乱码方案   

2008-12-17 12:28:55|  分类: 技术 |  标签:  |字号  订阅

使用 httpclient 通信时分两种乱码。

1.向服务器post/get中文乱码

解决方法:查看源代码

public String getContentCharset() {
        String charset = (String) getParameter(HTTP_CONTENT_CHARSET);
        if (charset == null) {
            LOG.warn("Default content charset not configured, using ISO-8859-1");
            charset = "ISO-8859-1";
        }
        return charset;
    }

一目了然如果http 消息中header 设置charset可以解决问题。

method.addRequestHeader("Content-Type", "text/html; charset=gb2312");

2.获得服务器返回的中文乱码

问题分析

不过在实际使用中, 还是发现按照最基本的方式调用 HttpClient 时, 并不支持 UTF-8 编码, 在网络上找过一些文章, 也不得要领, 于是查看了 commons-httpclient-3.0.1 的一些代码, 首先在 PostMethod 中找到了 generateRequestEntity() 方法:

/**

* Generates a request entity from the post parameters, if present. Calls

* {@link EntityEnclosingMethod#generateRequestBody()} if parameters have not been set.

*

* @since 3.0

*/

protected RequestEntity generateRequestEntity() {

if (!this.params.isEmpty()) {

// Use a ByteArrayRequestEntity instead of a StringRequestEntity.

// This is to avoid potential encoding issues. Form url encoded strings

// are ASCII by definition but the content type may not be. Treating the content

// as bytes allows us to keep the current charset without worrying about how

// this charset will effect the encoding of the form url encoded string.

String content = EncodingUtil.formUrlEncode(getParameters(), getRequestCharSet());

ByteArrayRequestEntity entity = new ByteArrayRequestEntity(

EncodingUtil.getAsciiBytes(content),

FORM_URL_ENCODED_CONTENT_TYPE

);

return entity;

} else {

return super.generateRequestEntity();

}

}

原来使用 NameValuePair 加入的 HTTP 请求的参数最终都会转化为 RequestEntity 提交到 HTTP 服务器, 接着在 PostMethod 的父类 EntityEnclosingMethod 中找到了如下的代码:

/**

* Returns the request's charset. The charset is parsed from the request entity's

* content type, unless the content type header has been set manually.

*

* @see RequestEntity#getContentType()

*

* @since 3.0

*/

public String getRequestCharSet() {

if (getRequestHeader("Content-Type") == null) {

// check the content type from request entity

// We can't call getRequestEntity() since it will probably call

// this method.

if (this.requestEntity != null) {

return getContentCharSet(

new Header("Content-Type", requestEntity.getContentType()));

} else {

return super.getRequestCharSet();

}

} else {

return super.getRequestCharSet();

}

}

 

解决方案

从上面两段代码可以看出是 HttpClient 是如何依据 "Content-Type" 获得请求的编码(字符集), 而这个编码又是如何应用到提交内容的编码过程中去的. 按照这个原来, 其实我们只需要重载 getRequestCharSet() 方法, 返回我们需要的编码(字符集)名称, 就可以解决 UTF-8 或者其它非默认编码提交 POST 请求时的乱码问题了.

测试

首先在 Tomcat 的 ROOT WebApp 下部署一个页面 test.jsp, 作为测试页面, 主要代码片段如下:

<%@ page contentType="text/html;charset=UTF-8"%>

<%@ page session="false" %>

<%

request.setCharacterEncoding("UTF-8");

String val = request.getParameter("TEXT");

System.out.println(">>>> The result is " + val);

%>

接着写一个测试类, 主要代码如下:

public static void main(String[] args) throws Exception, IOException {

String url = "http://localhost:8080/test.jsp";

PostMethod postMethod = new UTF8PostMethod(url);

//填入各个表单域的值

NameValuePair[] data = {

new NameValuePair("TEXT", "中文"),

};

//将表单的值放入postMethod中

postMethod.setRequestBody(data);

//执行postMethod

HttpClient httpClient = new HttpClient();

httpClient.executeMethod(postMethod);

}

//Inner class for UTF-8 support

public static class UTF8PostMethod extends PostMethod{

public UTF8PostMethod(String url){

super(url);

}

@Override

public String getRequestCharSet() {

//return super.getRequestCharSet();

return "UTF-8";

}

}

运行这个测试程序, 在 Tomcat 的后台输出中可以正确打印出 ">>>> The result is 中文" .

代码下载

本文所提到的所有代码, 以及测试程序(可直接导入 eclipse)提供打包下载: att:HttpClient POST 的 UTF-8 编码问题.httpClientUTF8.tar.bz2
}
} else {
return super.getRequestCharSet();
}
}

 

参考资料:http://thinkbase.net/w/main/Wiki?HttpClient+POST+%E7%9A%84+UTF-8+%E7%BC%96%E7%A0%81%E9%97%AE%E9%A2%98

posted on 2012-12-01 16:25  lexus  阅读(485)  评论(0编辑  收藏  举报