Spring Boot中文乱码问题解决方案:亲测有效

作者: 狄仁杰666 | 来源:发表于2020-11-15 23:42 被阅读0次

    前言

    来啦老铁!

    笔者学习Spring Boot有一段时间了,附上Spring Boot系列学习文章,欢迎取阅、赐教:

    1. 5分钟入手Spring Boot;
    2. Spring Boot数据库交互之Spring Data JPA;
    3. Spring Boot数据库交互之Mybatis;
    4. Spring Boot视图技术;
    5. Spring Boot之整合Swagger;
    6. Spring Boot之junit单元测试踩坑;
    7. 如何在Spring Boot中使用TestNG;
    8. Spring Boot之整合logback日志;
    9. Spring Boot之整合Spring Batch:批处理与任务调度;
    10. Spring Boot之整合Spring Security: 访问认证;
    11. Spring Boot之整合Spring Security: 授权管理;
    12. Spring Boot之多数据库源:极简方案;
    13. Spring Boot之使用MongoDB数据库源;
    14. Spring Boot之多线程、异步:@Async;
    15. Spring Boot之前后端分离(一):Vue前端;
    16. Spring Boot之前后端分离(二):后端、前后端集成;
    17. Spring Boot之前后端分离(三):登录、登出、页面认证;
    18. Spring Boot之面向切面编程:Spring AOP;
    19. Spring Boot之集成Redis(一):Redis初入门;
    20. Spring Boot之集成Redis(二):集成Redis;
    21. Spring Boot之集成Redis(三):Spring Cache + Redis;
    22. Spring Boot之文件上传、下载;

    最近在憋Spring Boot应用的的一个大招,暂时还未能完成文章的编写,今天就来介绍一个小小的知识点吧:

    • 如何解决Spring Boot中的中文乱码问题?

    整体步骤

    1. 编写返回内容包含中文的API;
    2. 中文乱码演示;
    3. 解决中文乱码:(方法一);
    4. 解决中文乱码:(方法二);
    5. 解决中文乱码:(方法三)- 全局解决中文乱码问题;
    6. 中文正常显示演示;
    7. 中文乱码原因分析;

    1. 编写返回内容包含中文的API;

    随便在一个Spring Boot项目中的controller中添加一个API,如下:

    @GetMapping("/api/hello")
    public JSONObject sayHello() {
        JSONObject test = new JSONObject();
        test.put("name", "dylanz");
        test.put("say", "您好");
        return test;
    }
    

    2. 中文乱码演示;

    启动下项目后,请求API:http://127.0.0.1:8080/api/hello

    中文乱码演示

    我们会发现,API返回中,英文正常显示,而中文却乱码了!原因先不分析,我们先来看看怎么解决!

    3. 解决中文乱码:(方法一);

    如何解决呢,非常简单,修改一下API:

    @GetMapping("/api/hello")
    public JSONObject sayHello() {
        HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
        assert response != null;
        response.setCharacterEncoding("UTF-8");
    
        JSONObject test = new JSONObject();
        test.put("name", "dylanz");
        test.put("say", "您好");
        return test;
    }
    

    原理非常简单,就是在返回中的头部信息中指定字符集为UTF-8,亲测有效!

    修复中文乱码 指定字符集为UTF-8

    4. 解决中文乱码:(方法二);

    这种办法更为简单,比第一种还简单,只需要在API上指定produces即可,如:

    @GetMapping(value = "/api/hello", produces = "application/json;charset=UTF-8")
    public JSONObject sayHello() {
        JSONObject test = new JSONObject();
        test.put("name", "dylanz");
        test.put("say", "您好");
        return test;
    }
    

    这种方式同样可以解决中文乱码问题,亲测有效!

    5. 解决中文乱码:(方法三)- 全局解决中文乱码问题;

    上述解决中文乱码的2种方式固然简单,但需要一个一个API添加,这不符合咱们的气质啊,正确的姿势应该是:全局解决中文乱码问题!

    在config包内新建CharsetConfig.java类(类名不限,不是非得CharsetConfig),在该配置类中写入代码:
    package com.github.dylanz666.config;
    
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import com.alibaba.fastjson.support.config.FastJsonConfig;
    import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.StringHttpMessageConverter;
    import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
    
    import java.nio.charset.StandardCharsets;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author : dylanz
     * @since : 11/15/2020
     */
    @Configuration
    public class CharsetConfig extends WebMvcConfigurationSupport {
        @Bean
        public HttpMessageConverter<String> responseBodyConverter() {
            return new StringHttpMessageConverter(
                    StandardCharsets.UTF_8);
        }
    
        @Override
        public void configureMessageConverters(
                List<HttpMessageConverter<?>> converters) {
            super.configureMessageConverters(converters);
            converters.add(responseBodyConverter());
    
            FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
            FastJsonConfig fastJsonConfig = new FastJsonConfig();
            fastJsonConfig.setSerializerFeatures(
                    SerializerFeature.PrettyFormat
            );
            List<MediaType> fastMediaTypes = new ArrayList<>();
            fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
            fastConverter.setSupportedMediaTypes(fastMediaTypes);
            fastConverter.setFastJsonConfig(fastJsonConfig);
    
            converters.add(fastConverter);
        }
    
        @Override
        public void configureContentNegotiation(
                ContentNegotiationConfigurer configurer) {
            configurer.favorPathExtension(false);
        }
    }
    

    由于我使用的是fastjson,因此在configureMessageConverters中添加了fastjson对中文支持的配置代码。

    编写完成后,删除(方法一)和(方法二)的支持代码后,重启项目,中文支持已经变成全局生效啦,亲测有效!

    6. 中文正常显示演示;

    中文正常显示演示

    7. 中文乱码原因分析;

    1). 借用第三步解决乱码问题的代码,稍微做一下修改,打印出修改前的字符集:
    @GetMapping("/api/hello")
    public JSONObject sayHello() {
        HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
        assert response != null;
        System.out.println("Default charset: " + response.getCharacterEncoding());
    
        JSONObject test = new JSONObject();
        test.put("name", "dylanz");
        test.put("say", "您好");
        return test;
    }
    
    2). 再次启动项目并访问API后:
    中文乱码原因

    原因找到了,原来Spring Boot中的JSON默认字符集是:ISO-8859-1(如果返回是纯String,则字符集为UTF-8,且中文不会乱码)。

    从浏览器或postman上也能看出默认的字符集设置:

    默认字符集
    3). 我们解决乱码后的字符集:
    image.png

    至此,我们从2个维度、3种方法,解决了Spring Boot项目中中文乱码的问题:

    • API单独设置字符集;
    • 全局设置字符集;

    要我说,肯定是全局设置字符集更香啊,您说呢?

    如果本文对您有帮助,麻烦点赞、关注!

    谢谢!

    相关文章

      网友评论

        本文标题:Spring Boot中文乱码问题解决方案:亲测有效

        本文链接:https://www.haomeiwen.com/subject/tlpobktx.html