zoukankan      html  css  js  c++  java
  • RestTemplate--解决中文乱码

    【原文链接】:https://blog.tecchen.xyz ,博文同步发布到博客园。
    由于精力有限,对文章的更新可能不能及时同步,请点击上面的原文链接访问最新内容。
    欢迎访问我的个人网站:https://www.tecchen.xyz

    在开发扇贝-每日一句时,使用RestTemplate请求扇贝接口,并保存返回的数据。原本正常的代码,经过架构升级后,请求接口时,会返回乱码数据。经过直接访问接口等形式,最终确认是RestTemplate这个bean有问题。
    对RestTemplate的声明也比较简单,通过对apache的httpclient进行封装,返回bean实例。代码如下:

    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate(httpRequestFactory());
    }
    
    

    通过断点debug发现以String格式接收数据时,底层采用的是StringHttpMessageConverter来处理请求。查看RestTemplate的构造方法如下:

    public RestTemplate() {
        this.messageConverters = new ArrayList();
        this.errorHandler = new DefaultResponseErrorHandler();
        this.uriTemplateHandler = new DefaultUriBuilderFactory();
        this.headersExtractor = new RestTemplate.HeadersExtractor();
        this.messageConverters.add(new ByteArrayHttpMessageConverter());
        this.messageConverters.add(new StringHttpMessageConverter());
        this.messageConverters.add(new ResourceHttpMessageConverter(false));
        this.messageConverters.add(new SourceHttpMessageConverter());
        this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        if (romePresent) {
            this.messageConverters.add(new AtomFeedHttpMessageConverter());
            this.messageConverters.add(new RssChannelHttpMessageConverter());
        }
    
        if (jackson2XmlPresent) {
            this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
        } else if (jaxb2Present) {
            this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
        }
    
        if (jackson2Present) {
            this.messageConverters.add(new MappingJackson2HttpMessageConverter());
        } else if (gsonPresent) {
            this.messageConverters.add(new GsonHttpMessageConverter());
        } else if (jsonbPresent) {
            this.messageConverters.add(new JsonbHttpMessageConverter());
        }
    
        if (jackson2SmilePresent) {
            this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
        }
    
        if (jackson2CborPresent) {
            this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
        }
    }
    

    其中的StringHttpMessageConverter构造方法使用了默认字符集:ISO-8859-1。

    public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
        public static final Charset DEFAULT_CHARSET;
        ……
        public StringHttpMessageConverter() {
            this(DEFAULT_CHARSET);
        }
        ……
        static {
            DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
        }
    }
    

    private final List<HttpMessageConverter<?>> messageConverters
    根据RestTemplate的构造方法的源码得知所有的HttpMessageConverter都是放在final List<HttpMessageConverter<?>> messageConverters这个常量集合中。虽然集合不可修改,但是可以对其中的元素StringHttpMessageConverter进行修改。
    解决方案思路都是将ISO-8859-1的StringHttpMessageConverter替换为UTF-8的StringHttpMessageConverter。

    • 示例代码一
    restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
    
    • 示例代码二
    for (HttpMessageConverter<?> httpMessageConverter : restTemplate.getMessageConverters()) {
        if (httpMessageConverter instanceof StringHttpMessageConverter) {
            ((StringHttpMessageConverter) httpMessageConverter).setDefaultCharset(Charset.forName("UTF-8"));
        }
    }
    
    • 示例代码三
    // stream .findFirst(); 也是可以的
    Optional<HttpMessageConverter<?>> converter = restTemplate.getMessageConverters().stream().filter(c -> c instanceof StringHttpMessageConverter).findAny();
    if(converter.isPresent()) {
        ((StringHttpMessageConverter) converter.get()).setDefaultCharset(Charset.forName("UTF-8"));
    }
    
  • 相关阅读:
    【java】一种自动生成数据库文档的方法
    sublime vintage mode 按住一个键(比如 j)不会重复的问题
    SQL Service服务更换帐户后无法启动的情况(Security 4625 Type 5)
    隐藏的计划任务运行,导致账户被锁的调查方法
    nodejs 热更新页面
    数组转tree arrToTree
    compose函数
    react 类组件的生命周期
    qiankun 微应用demo
    application 'xxx' died in status LOADING_SOURCE_CODE: [qiankun] You need to export lifecycle functions in xxx entry
  • 原文地址:https://www.cnblogs.com/Candies/p/10398584.html
Copyright © 2011-2022 走看看