HTTP Content-Type与Content-Encoding

393 阅读2分钟

问题

线上海外有非中文或者英文,如果发送HTTP请求时,使用json格式,但是没有指定字符集,而服务端在解析的时候使用Jackson反序列化的时候,会有反序列化失败的情况。

HttpPost httpPost = new HttpPost(uri);
httpPost.setConfig(requestConfig);
StringEntity entity = new StringEntity(JsonUtils.toJSON(object), ContentType.APPLICATION_JSON);
//ByteArrayEntity entity = new ByteArrayEntity(JsonUtils.toJSON(object).getBytes(StandardCharsets.UTF_8));
//entity.setContentEncoding("UTF-8");
//没必要重复设置,因为在StringEntity已经设置了。
//entity.setContentType("application/json;charset=UTF-8");
httpPost.setEntity(entity);
return httpClient.execute(httpPost, handler);

如果只是使用StringEntity entity = new StringEntity(JsonUtils.toJSON(object));会有服务端反序列化失败的问题。

    /**
     * Creates a StringEntity with the specified content. The content type defaults to
     * {@link ContentType#TEXT_PLAIN}.
     *
     * @param string content to be used. Not {@code null}.
     *
     * @throws IllegalArgumentException if the string parameter is null
     * @throws UnsupportedEncodingException if the default HTTP charset is not supported.
     */
    public StringEntity(final String string)
            throws UnsupportedEncodingException {
        this(string, ContentType.DEFAULT_TEXT);
    }
    
    public static final ContentType DEFAULT_TEXT = TEXT_PLAIN;
    // 默认字符集为ISO_8859_1
    public static final ContentType TEXT_PLAIN = create(
            "text/plain", Consts.ISO_8859_1);
    // JSON的字符集为UTF_8        
    public static final ContentType APPLICATION_JSON = create(
            "application/json", Consts.UTF_8);
public StringEntity(final String string, final ContentType contentType) throws UnsupportedCharsetException {
    super();
    Args.notNull(string, "Source string");
    Charset charset = contentType != null ? contentType.getCharset() : null;
    if (charset == null) {
        charset = HTTP.DEF_CONTENT_CHARSET;
    }
    // 关键问题在此!!!
    this.content = string.getBytes(charset);
    if (contentType != null) {
        // 所以在业务代码上,没必要重复设置
        setContentType(contentType.toString());
    }
}

Jackson在反序列化的时候会探测反序列化内容的字符集。

Content-Type

用于定义消息体的类型:常见的如application/json,text/plain。

Content-Encoding

content-encoding表示的是压缩算法,一般只出现在服务端。浏览器通过Accept-Encoding告知服务端,浏览器可以支持的压缩算法,服务端从中选择一种,将返回内容按照该压缩算法压缩内容,返回给浏览器。浏览器按照response中的Content-Encoding来解压缩。

客户端也可以将请求体进行压缩,但是需要服务端自己支持。

参考