SpringBoot基礎(chǔ)系列之自定義配置源使用姿勢實例演示

image

【SpringBoot基礎(chǔ)系列】自定義配置源的使用姿勢介紹

前面一篇博文介紹了一個@Value的一些知識點降允,其中提了一個點,@Value對應(yīng)的配置,除了是配置文件中之外递惋,可以從其他的數(shù)據(jù)源中獲取么搔弄,如從 redis竹宋,db救斑,http 中獲取配置泵琳?

了解過 SpringCloud Config 的可以給出確切的答案心褐,可以舔涎,而且用起來還老爽了,遠(yuǎn)程配置逗爹,支持配置動態(tài)刷新亡嫌,接下來我們來看一下,在 SpringBoot 中掘而,如何配置自定義的數(shù)據(jù)源

I. 項目環(huán)境

1. 項目依賴

本項目借助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA進行開發(fā)

開一個 web 服務(wù)用于測試

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

II. 自定義配置源

@Value修飾的成員挟冠,綁定配置時,是從Envrionment中讀取配置的袍睡,所以我們需要做的就是注冊一個自定義的配置源知染,借助MapPropertySource可以來實現(xiàn)我們需求場景

1. 自定義數(shù)據(jù)源

演示一個最簡單自定義的配置數(shù)據(jù)源,重寫MapPropertySourcegetProperties方法

實現(xiàn)如下

public class SimplePropertiesSource extends MapPropertySource {
    public SimplePropertiesSource(String name, Map<String, Object> source) {
        super(name, source);
    }

    public SimplePropertiesSource() {
        this("filePropertiesSource", new HashMap<>());
    }

    /**
     * 覆蓋這個方法女蜈,適用于實時獲取配置
     *
     * @param name
     * @return
     */
    @Override
    public Object getProperty(String name) {
        // 注意持舆,只針對自定義開頭的配置才執(zhí)行這個邏輯
        if (name.startsWith("selfdefine.")) {
            return name + "_" + UUID.randomUUID();
        }
        return super.getProperty(name);
    }
}

2. 數(shù)據(jù)源注冊

上面只是聲明了配置源,接下來把它注冊到 Environment 中伪窖,這樣就可以供應(yīng)用使用了

@RestController
@SpringBootApplication
public class Application {
    private Environment environment;

    @Bean
    public SimplePropertiesSource simplePropertiesSource(ConfigurableEnvironment environment) {
        this.environment = environment;
        SimplePropertiesSource ropertiesSource = new SimplePropertiesSource();
        environment.getPropertySources().addLast(ropertiesSource);
        return ropertiesSource;
    }

    // 獲取配置
    @GetMapping(path = "get")
    public String getProperty(String key) {
        return environment.getProperty(key);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}
image

從上面的輸出可以看出逸寓,自定義配置開頭的會獲取到隨機的配置值;非selfdefine開頭的覆山,沒有相應(yīng)的配置竹伸,返回空

3. 基于文件的自定義配置源

上面這個可能有點過于兒戲了,接下來我們將配置源放在自定義的文件中簇宽,并支持文件配置修改

public class FilePropertiesSource extends MapPropertySource {
    public FilePropertiesSource(String name, Map<String, Object> source) {
        super(name, source);
    }

    public FilePropertiesSource() {
        this("filePropertiesSource", new HashMap<>());
    }

    // 這種方式勋篓,適用于一次撈取所有的配置,然后從內(nèi)存中查詢對應(yīng)的配置魏割,提高服務(wù)性能
    // 10s 更新一次
    @PostConstruct
    @Scheduled(fixedRate = 10_000)
    public void refreshSource() throws IOException {
        String ans =
                FileCopyUtils.copyToString(new InputStreamReader(FilePropertiesSource.class.getClassLoader().getResourceAsStream("kv.properties")));
        Map<String, Object> map = new HashMap<>();
        for (String sub : ans.split("\n")) {
            if (sub.isEmpty()) {
                continue;
            }
            String[] kv = StringUtils.split(sub, "=");
            if (kv.length != 2) {
                continue;
            }

            map.put(kv[0].trim(), kv[1].trim());
        }

        source.clear();
        source.putAll(map);
    }
}

上面寫了一個定時器譬嚣,每 10s 刷新一下內(nèi)存中的配置信息,當(dāng)然這里也是可以配置一個文件變動監(jiān)聽器钞它,相關(guān)有興趣的話拜银,可以看下Java 實現(xiàn)文件變動的監(jiān)聽可以怎么玩

對應(yīng)的配置文件

user=xhh
name=一灰灰
age=18

注冊的姿勢與上面一致殊鞭,就不單獨說明了,接下來演示一下使用

image

從上可以看到文件中的配置修改之后尼桶,過一段時間會刷新

4. @Value綁定自定義配置

接下來我們看一下操灿,將@Value綁定自定義的配置,是否可以成功

調(diào)整一下上面的 Application, 添加一個成員屬性

@Value("${name}")
private String name;

@GetMapping(path = "get")
public String getProperty(String key) {
    return name + "|" + environment.getProperty(key);
}

再次測試發(fā)現(xiàn)拋異常了泵督,說是這個配置不存在V貉巍!小腊!

image

(這就過分了啊救鲤,看了半天,結(jié)果告訴我不行溢豆,這還不得趕緊搞個差評么 ??????)

已經(jīng)寫到這里了蜒简,當(dāng)然我也得繼續(xù)嘗試挽救一下,為啥前面直接通過Environment可以拿到配置漩仙,但是@Value注解綁定就不行呢搓茬?

”罪魁禍?zhǔn)住熬驮谟诔跏蓟樞颍易远x的配置源队他,還沒有塞到Envrionment卷仑,你就開會著手綁定了,就像準(zhǔn)備給”一灰灰 blog“一個差評麸折,結(jié)果發(fā)現(xiàn)還沒關(guān)注...(好吧锡凝,我承認(rèn)沒關(guān)注也可以評論 ??)

根據(jù)既往的知識點(至于是哪些知識點,那就長話短說不了了垢啼,看下面幾篇精選的博文吧)

要解決這個問題窜锯,一個最簡單的方式如下

創(chuàng)建一個獨立的配置類,實現(xiàn)自定義數(shù)據(jù)源的注冊

@Configuration
public class AutoConfig {
    @Bean
    public FilePropertiesSource filePropertiesSource(ConfigurableEnvironment environment) {
        FilePropertiesSource filePropertiesSource = new FilePropertiesSource();
        environment.getPropertySources().addLast(filePropertiesSource);
        return filePropertiesSource;
    }
}

測試類上指定 bean 依賴

@DependsOn("filePropertiesSource")
@EnableScheduling
@RestController
@SpringBootApplication
public class Application {
    @Autowired
    private Environment environment;

    @Value("${name}")
    private String name;

    @GetMapping(path = "get")
    public String getProperty(String key) {
        return name + "|" + environment.getProperty(key);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

再次測試芭析,結(jié)果如下

image

從上面的演示動圖可以看到锚扎,綁定自定義的數(shù)據(jù)源配置,沒有問題馁启,但是驾孔,當(dāng)配置變更時,綁定的 name 字段惯疙,沒有隨之更新

簡單來講就是不支持動態(tài)刷新翠勉,這就難受了啊,我就想要動態(tài)刷新霉颠,那該怎么搞对碌?

  • 不要急,新的博文已經(jīng)安排上了蒿偎,下篇奉上(怕迷路的小伙伴朽们,不妨關(guān)注一下”一灰灰 blog“??)

5. 小結(jié)

最后按照慣例小結(jié)一下克伊,本文篇幅雖長,但知識點比較集中华坦,總結(jié)下來,兩句話搞定

  • 通過繼承MapPropertySource來實現(xiàn)自定義配置源不从,注冊到Envrionment可供@Value使用
  • 使用@Value綁定自定義配置源時惜姐,注意注冊的順序要早于 bean 的初始化

好的,到這里正文結(jié)束椿息, 我是一灰灰歹袁,歡迎各位大佬來踩一踩長草的公眾號"一灰灰 blog"

III. 不能錯過的源碼和相關(guān)知識點

0. 項目

配置系列博文

1. 一灰灰 Blog

盡信書則不如,以上內(nèi)容寝优,純屬一家之言条舔,因個人能力有限,難免有疏漏和錯誤之處乏矾,如發(fā)現(xiàn) bug 或者有更好的建議孟抗,歡迎批評指正,不吝感激

下面一灰灰的個人博客钻心,記錄所有學(xué)習(xí)和工作中的博文凄硼,歡迎大家前去逛逛

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捷沸,隨后出現(xiàn)的幾起案子摊沉,更是在濱河造成了極大的恐慌,老刑警劉巖痒给,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件说墨,死亡現(xiàn)場離奇詭異,居然都是意外死亡苍柏,警方通過查閱死者的電腦和手機尼斧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來序仙,“玉大人突颊,你說我怎么就攤上這事∨说浚” “怎么了律秃?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長治唤。 經(jīng)常有香客問我棒动,道長,這世上最難降的妖魔是什么宾添? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任船惨,我火速辦了婚禮柜裸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘粱锐。我一直安慰自己疙挺,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布怜浅。 她就那樣靜靜地躺著铐然,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恶座。 梳的紋絲不亂的頭發(fā)上搀暑,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機與錄音跨琳,去河邊找鬼自点。 笑死,一個胖子當(dāng)著我的面吹牛脉让,可吹牛的內(nèi)容都是我干的桂敛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼侠鳄,長吁一口氣:“原來是場噩夢啊……” “哼埠啃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起伟恶,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤碴开,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后博秫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潦牛,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年挡育,在試婚紗的時候發(fā)現(xiàn)自己被綠了肤寝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘿般。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出汞幢,到底是詐尸還是另有隱情儡湾,我是刑警寧澤眼溶,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布授药,位于F島的核電站,受9級特大地震影響凹嘲,放射性物質(zhì)發(fā)生泄漏师倔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一周蹭、第九天 我趴在偏房一處隱蔽的房頂上張望趋艘。 院中可真熱鬧疲恢,春花似錦、人聲如沸瓷胧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搓萧。三九已至萎攒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矛绘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工刃永, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留货矮,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓斯够,卻偏偏與公主長得像囚玫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子读规,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

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