The Perfect Solution of RestTemplate Chinese Scrambling

Keywords: Java encoding network Spring

RestTemplate uses the default encoding in String HttpMessageConverter for Strings

public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
    //Eliminate other code
    public static final Charset DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
}

In ISO_8859_1 encoding lattice, Chinese is disorderly. So we need to set the encoding format to UTF-8 format to support Chinese.
Most tutorials on the network modify the encoding format in the following ways

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

The reason is that in the Constructor of RestTemplate, when assigning messageConverters, the StringHttpMessageConverter object is set at the position of subscript 1.

public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {
    public RestTemplate() {
        this.messageConverters.add(new ByteArrayHttpMessageConverter());
        this.messageConverters.add(new StringHttpMessageConverter());//Set up here
        this.messageConverters.add(new ResourceHttpMessageConverter(false));
        //Eliminate other code
    }
}

But this way of writing dead subscripts is highly undesirable, because it does not rule out the problem of subscription changes caused by Spring's introduction of other converters in subsequent versions. The following methods are recommended.

public static void setRestTemplateEncode(RestTemplate restTemplate) {
    if (null == restTemplate || ObjectUtils.isEmpty(restTemplate.getMessageConverters())) {
        return;
    }

    List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
    for (int i = 0; i < messageConverters.size(); i++) {
        HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
        if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
            messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        }
    }
}

We add a new method to pass in RestTemplate objects, traverse message Converters internally, find StringHttpMessageConverter and replace it with StringHttpMessageConverter objects in UTF-8 format.

The above way can be tested by oneself. If using the above way or random code, you can check whether there is no coding format in the back end.

Posted by itarun on Thu, 10 Oct 2019 09:22:22 -0700