Spring Boot中文亂碼問(wèn)題解決方案:親測(cè)有效

前言

來(lái)啦老鐵界睁!

筆者學(xué)習(xí)Spring Boot有一段時(shí)間了,附上Spring Boot系列學(xué)習(xí)文章旭寿,歡迎取閱捷枯、賜教:

  1. 5分鐘入手Spring Boot;
  2. Spring Boot數(shù)據(jù)庫(kù)交互之Spring Data JPA;
  3. Spring Boot數(shù)據(jù)庫(kù)交互之Mybatis;
  4. Spring Boot視圖技術(shù);
  5. Spring Boot之整合Swagger;
  6. Spring Boot之junit單元測(cè)試踩坑;
  7. 如何在Spring Boot中使用TestNG;
  8. Spring Boot之整合logback日志;
  9. Spring Boot之整合Spring Batch:批處理與任務(wù)調(diào)度;
  10. Spring Boot之整合Spring Security: 訪問(wèn)認(rèn)證;
  11. Spring Boot之整合Spring Security: 授權(quán)管理;
  12. Spring Boot之多數(shù)據(jù)庫(kù)源:極簡(jiǎn)方案;
  13. Spring Boot之使用MongoDB數(shù)據(jù)庫(kù)源;
  14. Spring Boot之多線程、異步:@Async;
  15. Spring Boot之前后端分離(一):Vue前端;
  16. Spring Boot之前后端分離(二):后端远豺、前后端集成;
  17. Spring Boot之前后端分離(三):登錄奈偏、登出、頁(yè)面認(rèn)證;
  18. Spring Boot之面向切面編程:Spring AOP;
  19. Spring Boot之集成Redis(一):Redis初入門(mén);
  20. Spring Boot之集成Redis(二):集成Redis;
  21. Spring Boot之集成Redis(三):Spring Cache + Redis;
  22. Spring Boot之文件上傳憋飞、下載;

最近在憋Spring Boot應(yīng)用的的一個(gè)大招霎苗,暫時(shí)還未能完成文章的編寫(xiě)姆吭,今天就來(lái)介紹一個(gè)小小的知識(shí)點(diǎn)吧:

  • 如何解決Spring Boot中的中文亂碼問(wèn)題榛做?

整體步驟

  1. 編寫(xiě)返回內(nèi)容包含中文的API;
  2. 中文亂碼演示;
  3. 解決中文亂碼:(方法一)检眯;
  4. 解決中文亂碼:(方法二)厘擂;
  5. 解決中文亂碼:(方法三)- 全局解決中文亂碼問(wèn)題;
  6. 中文正常顯示演示锰瘸;
  7. 中文亂碼原因分析刽严;

1. 編寫(xiě)返回內(nèi)容包含中文的API;

隨便在一個(gè)Spring Boot項(xiàng)目中的controller中添加一個(gè)API避凝,如下:

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

2. 中文亂碼演示舞萄;

啟動(dòng)下項(xiàng)目后,請(qǐng)求API:http://127.0.0.1:8080/api/hello

中文亂碼演示

我們會(huì)發(fā)現(xiàn)管削,API返回中倒脓,英文正常顯示,而中文卻亂碼了含思!原因先不分析崎弃,我們先來(lái)看看怎么解決!

3. 解決中文亂碼:(方法一)含潘;

如何解決呢饲做,非常簡(jiǎn)單,修改一下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;
}

原理非常簡(jiǎn)單遏弱,就是在返回中的頭部信息中指定字符集為UTF-8盆均,親測(cè)有效!

修復(fù)中文亂碼
指定字符集為UTF-8

4. 解決中文亂碼:(方法二)腾窝;

這種辦法更為簡(jiǎn)單缀踪,比第一種還簡(jiǎn)單,只需要在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;
}

這種方式同樣可以解決中文亂碼問(wèn)題驴娃,親測(cè)有效!

5. 解決中文亂碼:(方法三)- 全局解決中文亂碼問(wèn)題循集;

上述解決中文亂碼的2種方式固然簡(jiǎn)單唇敞,但需要一個(gè)一個(gè)API添加,這不符合咱們的氣質(zhì)啊咒彤,正確的姿勢(shì)應(yīng)該是:全局解決中文亂碼問(wèn)題疆柔!

在config包內(nèi)新建CharsetConfig.java類(lèi)(類(lèi)名不限,不是非得CharsetConfig)镶柱,在該配置類(lèi)中寫(xiě)入代碼:
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對(duì)中文支持的配置代碼。

編寫(xiě)完成后歇拆,刪除(方法一)和(方法二)的支持代碼后鞋屈,重啟項(xiàng)目范咨,中文支持已經(jīng)變成全局生效啦,親測(cè)有效厂庇!

6. 中文正常顯示演示渠啊;

中文正常顯示演示

7. 中文亂碼原因分析;

1). 借用第三步解決亂碼問(wèn)題的代碼权旷,稍微做一下修改替蛉,打印出修改前的字符集:
@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). 再次啟動(dòng)項(xiàng)目并訪問(wèn)API后:
中文亂碼原因

原因找到了,原來(lái)Spring Boot中的JSON默認(rèn)字符集是:ISO-8859-1(如果返回是純String拄氯,則字符集為UTF-8躲查,且中文不會(huì)亂碼)。

從瀏覽器或postman上也能看出默認(rèn)的字符集設(shè)置:

默認(rèn)字符集
3). 我們解決亂碼后的字符集:
image.png

至此译柏,我們從2個(gè)維度熙含、3種方法,解決了Spring Boot項(xiàng)目中中文亂碼的問(wèn)題:

  • API單獨(dú)設(shè)置字符集艇纺;
  • 全局設(shè)置字符集怎静;

要我說(shuō),肯定是全局設(shè)置字符集更香啊黔衡,您說(shuō)呢蚓聘?

如果本文對(duì)您有幫助,麻煩點(diǎn)贊盟劫、關(guān)注夜牡!

謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末侣签,一起剝皮案震驚了整個(gè)濱河市塘装,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌影所,老刑警劉巖勾给,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钧汹,死亡現(xiàn)場(chǎng)離奇詭異狸窘,居然都是意外死亡饿肺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)卷中,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)矛双,“玉大人,你說(shuō)我怎么就攤上這事蟆豫∫楹觯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵十减,是天一觀的道長(zhǎng)栈幸。 經(jīng)常有香客問(wèn)我毛雇,道長(zhǎng),這世上最難降的妖魔是什么侦镇? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮织阅,結(jié)果婚禮上壳繁,老公的妹妹穿的比我還像新娘。我一直安慰自己荔棉,他們只是感情好闹炉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著润樱,像睡著了一般渣触。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上壹若,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天嗅钻,我揣著相機(jī)與錄音,去河邊找鬼店展。 笑死养篓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赂蕴。 我是一名探鬼主播柳弄,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼概说!你這毒婦竟也來(lái)了碧注?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤糖赔,失蹤者是張志新(化名)和其女友劉穎萍丐,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體放典,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碉纺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刻撒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骨田。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖声怔,靈堂內(nèi)的尸體忽然破棺而出态贤,到底是詐尸還是另有隱情,我是刑警寧澤醋火,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布悠汽,位于F島的核電站箱吕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏柿冲。R本人自食惡果不足惜茬高,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望假抄。 院中可真熱鬧怎栽,春花似錦、人聲如沸宿饱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谬以。三九已至强饮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間为黎,已是汗流浹背邮丰。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铭乾,地道東北人柠座。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像片橡,于是被迫代替她去往敵國(guó)和親妈经。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容