1. 程式人生 > >解決HttpClient工具中application/x-www-form-urlencoded表單提交時,請求引數中文亂碼問題

解決HttpClient工具中application/x-www-form-urlencoded表單提交時,請求引數中文亂碼問題

一、引數亂碼現象

當我去請求第三方介面時,介面接收格式為Form表單的時候,使用HttpClient工具類。這時,對於封裝進HttpPost物件裡的請求引數,如果有中文引數,會出現亂碼的現象。

二、程式碼現象復現

controller層
@RestController
@RequestMapping(value = "/http")
public class HttpClientController {

    @GetMapping(value = "/get")
    public PrePayResultVO getHttpClientDemo() {

        String url = "https://xxxx.xxxx.com/xxxx/Xxxxx";
        Map map = new HashMap<>();
        map.put("cardId", "1234567890");
        map.put("carNumber", "粵LX255Q");
        map.put("parkCode", "1234567890");
        map.put("startTime", "2018-09-18");
        map.put("endTime", "2018-10-18");
        map.put("defferMoney", "0.01");

        JSONObject jsonObject = HttpClientUtils.postForForm(url, map);
        PrePayResultVO prePayResultVO =JSONObject.parseObject(jsonObject.toString(), PrePayResultVO.class);
        return prePayResultVO;
    }
}
httpClientUtils
public static JSONObject postForForm(String url, Map<String, String> parms) {
        HttpPost httpPost = new HttpPost(url);
        ArrayList<BasicNameValuePair> list = new ArrayList<>();
        parms.forEach((key, value) -> list.add(new BasicNameValuePair(key, value)));
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            if (Objects.nonNull(parms) && parms.size() >0) {
                httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
            }
            InputStream content = httpPost.getEntity().getContent();
            InputStreamReader inputStreamReader = new InputStreamReader(content, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String readLine = bufferedReader.readLine();
            System.out.println("readLine===================================" + readLine);
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity, "UTF-8"));
            return jsonObject;
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (Objects.nonNull(httpClient)){
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
列印結果

中文亂碼
由此可見,本應列印中的請求引數 “粵LX255Q”,卻變成了 “%E7%B2%A4LX255Q” 這種格式的字串。

三、產生原因

在我們發起請求時,瀏覽器首先會將這些中文字元進行編碼然後再發送給伺服器。實際上,瀏覽器會將它們轉換為 application/x-www-form-urlencoded MIME 字串。

四、解決方法

 public static JSONObject postForForm(String url, Map<String, String> parms) {
        HttpPost httpPost = new HttpPost(url);
        ArrayList<BasicNameValuePair> list = new ArrayList<>();
        parms.forEach((key, value) -> list.add(new BasicNameValuePair(key, value)));
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            if (Objects.nonNull(parms) && parms.size() >0) {
                httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
            }
            InputStream content = httpPost.getEntity().getContent();
            InputStreamReader inputStreamReader = new InputStreamReader(content, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String readLine = bufferedReader.readLine();
            String s = URLDecoder.decode(readLine, "UTF-8");
            System.out.println("readLine===================================" + readLine);
            System.out.println("s==========================================" + s);
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity, "UTF-8"));
            return jsonObject;
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (Objects.nonNull(httpClient)){
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

在獲取請求引數時,再對其使用URLDecoder將application/x-www-form-rulencoded MIME字串轉換為對應編碼的普通字串。

列印結果

解決方法

五、URLDecoder和URLEncoder的使用總結

  • URLDecoder類包含一個decode(String s,String enc)靜態方法,它可以將application/x-www-form-urlencoded MIME字串轉成普通字串;

  • URLEncoder類包含一個encode(String s,String enc)靜態方法,它可以將普通字串轉換成application/x-www-form-urlencoded MIME字串。

public static void main(String[] args) throws UnsupportedEncodingException {
        String name = "千夜";

        String decode = URLDecoder.decode("%E5%8D%83%E5%A4%9C", "UTF-8");
        System.out.println("application/x-www-form-urlencoded MIME字串轉成普通字串===============" + decode);
        String encode = URLEncoder.encode(name, "UTF-8");
        System.out.println("普通字串轉換成application/x-www-form-urlencoded MIME字串=============" +encode);
    }