Spring properties文件中文亂碼的原因及解決方案

先看看原情況以及效果圖

image.png

說到亂碼問題剃盾,其實目前遇到的亂碼問題原因可以歸根為讀取協(xié)議不對等,例如使用GBK文件格式去讀取UTF-8文件格式的內(nèi)容肯定會出現(xiàn)亂碼贝咙,那么我們解決問題的整體思路也就是使用合適的讀取格式去讀取文件內(nèi)容

本篇學(xué)習(xí)筆記代碼地址在simple-spring 的spring-learn模塊的bpp文件夾中

在此感謝 antz_H 的指正讶泰,此筆記只是本人在學(xué)習(xí)調(diào)試Spring代碼時弄的馒闷,啟動的方法也是ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext( new String[]{"spring/spring-bpp.xml"}) 不適用于SpringBoot常規(guī)的情況下,SpringBoot已經(jīng)提供了現(xiàn)成的@PropertySource 注解 解決方案

Properties 文件讀取

在之前的學(xué)習(xí)筆記中Spring Properties屬性獲取 源碼學(xué)習(xí)归榕,也曾經(jīng)介紹過如何讀取@Value("${XXX}")在屬性文件中XXX對應(yīng)的值尸红。

PropertySourcesPlaceholderConfigurer 類是實現(xiàn)BeanFactoryPostProcessor接口的,在執(zhí)行postProcessBeanFactory方法的時候刹泄,會進行屬性文件的讀取并且把鍵值對信息存儲到PropertySourcesPlaceholderConfigurer類本身的容器中

在抽象類PropertiesLoaderSupport的protected void loadProperties(Properties props) throws IOException方法去完成屬性文件內(nèi)容的讀取

最后來到了PropertiesLoaderUtils工具類中

    static void fillProperties(Properties props, EncodedResource resource, PropertiesPersister persister)
            throws IOException {

        InputStream stream = null;
        Reader reader = null;
        try {
            String filename = resource.getResource().getFilename();
            // 獲取文件名稱
            if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
                  // 1處 文件名不為null外里,而且是xml結(jié)尾
                stream = resource.getInputStream();
                persister.loadFromXml(props, stream);
            }
            else if (resource.requiresReader()) {
                  // 2處 如果resource中的encoding字段或者charset字段不為空
                    // 就會使用encoding內(nèi)的字符編碼或者charset設(shè)置的字符編碼格式讀取屬性文件
                reader = resource.getReader();
                persister.load(props, reader);
            }
            else {
                   // 3處 否則就是使用默認(rèn)的字符編碼獲取IO流
                stream = resource.getInputStream();
                persister.load(props, stream);
            }
        }

所以現(xiàn)在能夠解決當(dāng)前問題只有2處了,需要設(shè)置resource對象的encoding特石、charset字段值盅蝗,而此resource生成是使用了new EncodedResource(location, this.fileEncoding)實現(xiàn)的

現(xiàn)在解決方案已經(jīng)非常明了了,也就是設(shè)置PropertySourcesPlaceholderConfigurerbean的fileEncoding字段值即可

fileEncoding 字段值填充

xml配置的方法還是很簡單的,直接設(shè)置bean的基本參數(shù)姆蘸,然后在bean實例完之后參數(shù)填充即可

image

現(xiàn)在討論的是另一種情況墩莫,沒有對外直接的file-encoding字段設(shè)置能力

上面已經(jīng)說了芙委,調(diào)用postProcessBeanFactory方法,會進行屬性文件的讀取(也就意味著PropertySourcesPlaceholderConfigurer是一個實現(xiàn)了BeanFactoryPostProcessor和PriorityOrdered接口的特殊BPP類)贼穆,那么就必須在這個方法調(diào)用前完成參數(shù)的注入

重點關(guān)注BPP處理的核心類PostProcessorRegistrationDelegate

可以提出兩種解決方案

  • 實現(xiàn)BeanDefinitionRegistryPostProcessor 接口
  • 實現(xiàn)BeanFactoryPostProcessor题山、PriorityOrdered 接口(排序超過PropertySourcesPlaceholderConfigurer)

至于為啥是這兩種方案,可以看看之前寫的Spring 鉤子之BeanFactoryPostProcessor和BeanPostProcessor的源碼學(xué)習(xí) 故痊、再談Spring BeanPostProcessor

例如如下自定義的BPP(具方法可看github內(nèi)的代碼)

@Component
public class PriorityOrderedBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
        PriorityOrdered {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        Map map = beanFactory.getBeansOfType(PropertySourcesPlaceholderConfigurer.class);
        // 可能存在多個PropertySourcesPlaceholderConfigurerbean的情況
        Iterator<Map.Entry<String, PropertySourcesPlaceholderConfigurer>> it = map.entrySet().iterator();

        while (it.hasNext()) {
            Map.Entry<String, PropertySourcesPlaceholderConfigurer> entry = it.next();
            PropertySourcesPlaceholderConfigurer pp = entry.getValue();
            pp.setFileEncoding("UTF-8");
            // 終于獲取到了設(shè)置文件編碼類型的地方了
            // 這也是最關(guān)鍵的地方
        }
    }

    @Override
    public int getOrder() {
        // 排序規(guī)則顶瞳,具體可以看看OrderComparator的排序規(guī)則
        // PropertySourcesPlaceholderConfigurer的排序order是最低的,所以設(shè)置一個0完全可以滿足要求
        return 0;
    }
}

總結(jié)

本學(xué)習(xí)筆記也可以算是又一篇BPP的實踐愕秫,一方面加深對BPP的了解慨菱,另一方面結(jié)合當(dāng)前遇到的具體問題具體解決,其實隨著對spring學(xué)習(xí)的深入會發(fā)現(xiàn)越來越多通過BPP擴展的功能戴甩,例如監(jiān)控spring-actuator也是利用BPP添加額外的端點完成相應(yīng)的功能

如果對BPP有更多興趣的符喝,PostProcessorRegistrationDelegate類需要來回琢磨,調(diào)試

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甜孤,一起剝皮案震驚了整個濱河市协饲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缴川,老刑警劉巖茉稠,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異把夸,居然都是意外死亡而线,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進店門恋日,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膀篮,“玉大人,你說我怎么就攤上這事岂膳∈母停” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵谈截,是天一觀的道長筷屡。 經(jīng)常有香客問我,道長傻盟,這世上最難降的妖魔是什么速蕊? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮娘赴,結(jié)果婚禮上规哲,老公的妹妹穿的比我還像新娘。我一直安慰自己诽表,他們只是感情好唉锌,可當(dāng)我...
    茶點故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布隅肥。 她就那樣靜靜地躺著,像睡著了一般袄简。 火紅的嫁衣襯著肌膚如雪腥放。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天绿语,我揣著相機與錄音秃症,去河邊找鬼。 笑死吕粹,一個胖子當(dāng)著我的面吹牛种柑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播匹耕,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼聚请,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了稳其?” 一聲冷哼從身側(cè)響起驶赏,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎既鞠,沒想到半個月后煤傍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡损趋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年患久,在試婚紗的時候發(fā)現(xiàn)自己被綠了椅寺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浑槽。...
    茶點故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖返帕,靈堂內(nèi)的尸體忽然破棺而出桐玻,到底是詐尸還是另有隱情,我是刑警寧澤荆萤,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布镊靴,位于F島的核電站,受9級特大地震影響链韭,放射性物質(zhì)發(fā)生泄漏偏竟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一敞峭、第九天 我趴在偏房一處隱蔽的房頂上張望踊谋。 院中可真熱鬧,春花似錦旋讹、人聲如沸殖蚕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽睦疫。三九已至害驹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛤育,已是汗流浹背宛官。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瓦糕,地道東北人摘刑。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像刻坊,于是被迫代替她去往敵國和親枷恕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,926評論 2 361

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理谭胚,服務(wù)發(fā)現(xiàn)徐块,斷路器,智...
    卡卡羅2017閱讀 134,719評論 18 139
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器灾而,...
    simoscode閱讀 6,723評論 2 22
  • 本來是準(zhǔn)備看一看Spring源碼的胡控。然后在知乎上看到來一個帖子,說有一群**自己連Spring官方文檔都沒有完全讀...
    此魚不得水閱讀 6,938評論 4 21
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,867評論 6 342
  • 要加“m”說明是MB旁趟,否則就是KB了. -Xms:初始值 -Xmx:最大值 -Xmn:最小值 java -Xms1...
    阿B和阿C閱讀 7,347評論 0 7