http://www.360doc.com/content/09/0915/15/61497_6003890.shtml不 过在实际使用中, 还是发现按照最基本的方式调用 HttpClient 时, 并不支持 UTF-8 编码, 在网络上找过一些文章, 也不得要领, 于是查看了 commons-httpClient3.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 中文" .

HttpClient POST 的 UTF-8 编码问题的更多相关文章

  1. 从Java String实例来理解ANSI、Unicode、BMP、UTF等编码概念

    转(http://www.codeceo.com/article/java-string-ansi-unicode-bmp-utf.html#0-tsina-1-10971-397232819ff9a ...

  2. .Net基础——程序集与CIL HttpClient封装方法 .Net Core 编码规范 C#中invoke和beginInvoke的使用 WebServeice 动态代理类

    .Net基础——程序集与CIL   1. 程序集和CIL: 程序集是由.NET语言的编译器接受源代码文件产生的输出文件,通常分为 exe和dll两类,其中exe包含Main入口方法可以双击执行,dll ...

  3. 文字编码ASCII,GB2312,GBK,GB18030,UNICODE,UCS,UTF的解析

    众所周知,一个文字从输入到显示到存储是有一个固定过程的,其过程为:输入码(根据输入法不同而不同)→机内码(根据语言环境不同而不同,不同的系统语言编码也不一样)→字型码(根据不同的字体而不同)→存储码( ...

  4. 字符集、字符编码、国际化、本地化简要总结(UNICODE/UTF/ASCII/GB2312/GBK/GB18030)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   普通的linux 和 普通的windows.    ...

  5. Python里的编码问题

    马克一篇 http://bbs.chinaunix.net/archiver/tid-1163613.html http://www.openhome.cc/Gossip/Python/ImportI ...

  6. JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码

    一.对象序列化 1.1.对象序列化 被操作的对象需要实现Serializable接口 1.2.对象序列化流ObjectOutputStream与ObjectInputStream ObjectInpu ...

  7. Java中常用的字符编码-解析

    ASCII字符编码 美国信息互换标准代码,为罗马字母编制的一套编码,主要用于表达现代英语和其他西欧语言中的字符,1字节的7位表示一个字符. ISO-8859-1字符编码 ISO为西欧语言中的字符制定的 ...

  8. HttpClient工具类v1.7

    package com.cucpay.fundswap.util; import java.io.IOException; import java.net.SocketTimeoutException ...

  9. 请问什么是UTF字符串?

    utf是编码方式,一般而言是国际性质的编码格式,有utf-8,utf-9,utf-16等多种形式,是最高级别的编码方式,也就是说如果你要读取的数据流设置成utf编码的话就要用到相应的编码方式来读取了, ...

随机推荐

  1. 建立新的acticity需要的注意的问题

    首先需要我们在mainifests中进行注册, <activity android:name="com.special.residemenudemo.CameraActivity&qu ...

  2. DFS之奇偶剪枝

    问题描述: 给定一个 N * M的迷宫+起点+终点 ,迷宫中有一些障碍无法穿过,问能否不重复也不停留地在刚好一共走 t 步出迷宫. 先上结论: 在理想情况下,s到e需要的最小步数为m=|ex-sx|+ ...

  3. 百度之星资格赛 2016 Problem 1002

    本文链接:http://www.cnblogs.com/Ash-ly/p/5494623.html 题意: 度熊面前有一个全是由1构成的字符串,被称为全1序列.你可以合并任意相邻的两个1,从而形成一个 ...

  4. 福州三中集训day4

    第6天写第4天的博客….可以说是很弱了…… 讲了一天的高级数据结构,可以说很迷,先是并查集,然后是树状数组,线段树,MAP函数,KMP算法. 很难……确实不是很清楚…但是很重要,回去以后这应该说是优先 ...

  5. 26、Django实战第26天:配置全局导航

    1.编辑index.html,继承base.html 2.编辑base.html,根据是否登录不同显示 问题:当我们选中一个导航,选中样式并没有成为选中的状态 因此我们编辑base.html对导航中进 ...

  6. 20、Django实战第20天:课程详情页

    1.把course-detail.html复制到templates目录下 2.编辑course-detail.html,分析页面,继承base.html 3.编辑courses.views .... ...

  7. Web应用程序指纹识别工具BlindElephant

    Web应用程序指纹识别工具BlindElephant   BlindElephant是一款Web应用程序指纹识别工具.该工具可以读取目标网站的特定静态文件,计算其对应的哈希值,然后和预先计算出的哈希值 ...

  8. [PKUSC2018]神仙的游戏(FFT)

    给定一个01?串,对所有len询问是否存在一种填法使存在长度为len的border. 首先有个套路的性质:对于一个长度为len的border,这个字符串一定有长度为n-len的循环节(最后可以不完整) ...

  9. 【BZOJ3167/4824】[Heoi2013]Sao/[Cqoi2017]老C的键盘

    [BZOJ3167][Heoi2013]Sao Description WelcometoSAO(StrangeandAbnormalOnline).这是一个VRMMORPG,含有n个关卡.但是,挑战 ...

  10. 【分块】hdu5057 Argestes and Sequence

    分块,v[i][j][k]表示第i块内第j位是k的元素数.非常好写.注意初始化 要注意题意,①第i位是从右往左算的. ②若x没有第i位,则用前导零补齐10位.比如103---->00000001 ...