org.apache.http.client.methods.HttpPost发送post请求时候表单数据中文乱码

昨天用httpclient的HttpPost发送带中文参数的数据去调试第三方接口时候,出现了中文乱码,见下面控制台打印信息的最后一行,city的中文值变成了%3F%3F%3F%3F%3F%3F。

09:29:49.383 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Executing request POST /xxx/xxx/xxx HTTP/1.1
09:29:49.383 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Target auth state: UNCHALLENGED
09:29:49.384 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Proxy auth state: UNCHALLENGED
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> POST /xxx/xxx/xxx HTTP/1.1
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Length: 99
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Type: application/x-www-form-urlencoded
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Host: xxx.xxx.xxx.xxx:8180
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Connection: Keep-Alive
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.3 (Java 1.5 minimum; Java/1.8.0_91)
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "POST /xxx/xxx/xxx HTTP/1.1[\r][\n]"
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Length: 99[\r][\n]"
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Host: xxx.xxx.xxx.xxx:8180[\r][\n]"
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
09:29:49.391 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.3 (Java 1.5 minimum; Java/1.8.0_91)[\r][\n]"
09:29:49.391 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
09:29:49.391 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
09:29:49.392 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "key=xxx&city=%3F%3F%3F%3F%3F%3F&agt=xxxx&depart=yyy"

下面是请求代码

public String executePost(String url, Map param) throws HttpException, IOException {
        String result = null;
        List nvps = HttpUtil.buildNameValuePair(param);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        EntityBuilder builder = EntityBuilder.create();
        try {
            HttpPost httpPost = new HttpPost(url);
            builder.setParameters(nvps);
            httpPost.setEntity(builder.build());
            CloseableHttpResponse response = httpclient.execute(httpPost);

            try {
                HttpEntity entity = response.getEntity();
                if (response.getStatusLine().getReasonPhrase().equals("OK") && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    result = EntityUtils.toString(entity, "UTF-8");
                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        return result;
    }

public static void main(String[] args) {
        HttpUtil helper = new HttpUtil();
        Map param = new HashMap<>();
        param.put("key", "xxx");
        param.put("agt", "xxx");
        param.put("depart", "yyy");
        param.put("city", "浙江省杭州市");
        String url = "http://xxx.xxx.xxx.xxx:8180/xxx/xxx/xxx";
        try {
            String ret = helper.executePost(url, param);
            System.out.println(ret);
        } catch (HttpException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

后来去百度找到了一种可行的解决方式,下面贴上修改后的请求代码

/**
     * 
     * @author 北北
     * @date 2017年11月9日上午9:53:23
     * @param url 请求路径
     * @param param 请求参数
     * @param charset 编码方式
     * @return
     * @throws HttpException
     * @throws IOException
     */
    public String executePost(String url, Map param, String charset) throws HttpException, IOException {
        String result = null;
        List nvps = HttpUtil.buildNameValuePair(param);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpPost httpPost = new HttpPost(url);
            UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(nvps, charset);
            httpPost.setEntity(uefEntity);
            CloseableHttpResponse response = httpclient.execute(httpPost);

            try {
                HttpEntity entity = response.getEntity();
                if (response.getStatusLine().getReasonPhrase().equals("OK") && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    result = EntityUtils.toString(entity, "UTF-8");
                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        return result;
    }

public static void main(String[] args) {
        HttpUtil helper = new HttpUtil();
        Map param = new HashMap<>();
        param.put("key", "xxx");
        param.put("agt", "xxx");
        param.put("depart", "yyy");
        param.put("city", "浙江省杭州市");
        String url = "http://xxx.xxx.xxx.xxx:8180/xxx/xxx/xxx";
        try {
            String ret = helper.executePost(url, param);
            System.out.println(ret);
        } catch (HttpException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

这里主要是将设置参数的类由EntityBuilder换成了UrlEncodedFormEntity,从名称上可以看出后者是对表单数据路径编码的。

参考文章: HttpClient使用详解

你可能感兴趣的:(org.apache.http.client.methods.HttpPost发送post请求时候表单数据中文乱码)