springboot回顧一,介紹,自動(dòng)以及自定義配置

從本質(zhì)上來(lái)說(shuō)尚揣,Spring Boot就是Spring掖举,它做了那些沒(méi)有它你自己也會(huì)去做的SpringBean配置。謝天謝地方篮,幸好有Spring,你不用再寫(xiě)這些樣板配置了匕得,可以專注于應(yīng)用程序的邏輯巾表,這些才是應(yīng)用程序獨(dú)一無(wú)二的東西。

spring的介紹

啟動(dòng)引導(dǎo)spring

package readinglist;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ReadingListApplication {
    public static void main(String[] args) {
        SpringApplication.run(ReadingListApplication.class, args);
    }
}

@SpringBootApplication:開(kāi)啟組件掃描和自動(dòng)配置
SpringApplication.run 負(fù)責(zé)啟動(dòng)引導(dǎo)應(yīng)用程序
@SpringBootApplication 將三個(gè)有用的注解組合在了一起考阱。

  • Spring的 @Configuration :標(biāo)明該類(lèi)使用Spring基于Java的配置惠猿。雖然本書(shū)不會(huì)寫(xiě)太多
    配置,但我們會(huì)更傾向于使用基于Java而不是XML的配置姜凄。
  • Spring的 @ComponentScan :?jiǎn)⒂媒M件掃描趾访,這樣你寫(xiě)的Web控制器類(lèi)和其他組件才能被
    自動(dòng)發(fā)現(xiàn)并注冊(cè)為Spring應(yīng)用程序上下文里的Bean。本章稍后會(huì)寫(xiě)一個(gè)簡(jiǎn)單的Spring MVC
    控制器申鱼,使用 @Controller 進(jìn)行注解云头,這樣組件掃描才能找到它。
  • Spring Boot 的 @EnableAutoConfiguration : 這 個(gè) 不 起 眼 的 小 注 解 也 可 以 稱 為
    @Abracadabra
    ① 匣砖,就是這一行配置開(kāi)啟了Spring Boot自動(dòng)配置的魔力昏滴,讓你不用再寫(xiě)成
    篇的配置了。

spring的自動(dòng)配置

在maven的依賴?yán)锩嫖覀儠?huì)看到一些starter之類(lèi)的依賴拂共,這個(gè)是啟動(dòng)依賴姻几,比如hibernate势告,在依賴之后spring就會(huì)為我們做一個(gè)自動(dòng)配置的事情培慌,那么我們?nèi)绻胍远x的配置的話柑爸,就需要用自定義的配置來(lái)覆蓋這個(gè)自定義的。

這里有個(gè)不錯(cuò)的例子:當(dāng)你在應(yīng)用程序里添加安全特性時(shí)馅而,自動(dòng)配置做得還不夠好譬圣。安全配置并不是放之四海而皆準(zhǔn)的,圍繞應(yīng)用程序安全有很多決策要做屯蹦,Spring Boot不能替你做決定绳姨。
雖然Spring Boot為安全提供了一些基本的自動(dòng)配置,但是你還是需要自己覆蓋一些配置以滿足特定的安全要求脑蠕。想知道如何用顯式的配置來(lái)覆蓋自動(dòng)配置跪削,我們先從為閱讀列表應(yīng)用程序添加SpringSecurity入手。在了解自動(dòng)配置提供了什么之后晃跺,我們?cè)賮?lái)覆蓋基礎(chǔ)的安全配置毫玖,以滿足特定的
場(chǎng)景需求。
首先我們配置一個(gè)

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .authorizeRequests()
    .antMatchers("/").access("hasRole('READER')")
    .antMatchers("/**").permitAll()
    .and()
    .formLogin()
    .loginPage("/login")
    .failureUrl("/login?error=true");
}
3.1 覆蓋 Spring Boot自動(dòng)配置 
@Override
protected void configure(
        AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(new UserDetailsService() {
              @Override
              public UserDetails loadUserByUsername(String username)
              throws UsernameNotFoundException {
              return readerRepository.findOne(username);
        }
    });
  }
}

那么自動(dòng)配置那邊是怎么檢測(cè)到這個(gè)類(lèi)然后并且覆蓋自動(dòng)配置類(lèi)呢?

@Configuration
@EnableConfigurationProperties
@ConditionalOnClass({ EnableWebSecurity.class })
@ConditionalOnMissingBean(WebSecurityConfiguration.class)
@ConditionalOnWebApplication
public class SpringBootWebSecurityConfiguration {
...
}

如你所見(jiàn)励背, SpringBootWebSecurityConfiguration 上加了好幾個(gè)注解砸西≈啡澹看到 @ConditionalOnClass 注解后衅疙,你就應(yīng)該知道Classpath里必須要有 @EnableWebSecurity 注解。
@ConditionalOnWebApplication 說(shuō) 明 這 必 須 是 個(gè) Web 應(yīng) 用 程 序 喧伞。 @ConditionalOn-MissingBean 注解才是我們的安全配置類(lèi)代替 SpringBootWebSecurityConfiguration 的關(guān)鍵所在绩郎。
@ConditionalOnMissingBean 注解要求當(dāng)下沒(méi)有WebSecurityConfiguration 類(lèi)型的Bean肋杖。雖然表面上我們并沒(méi)有這么一個(gè)Bean,但通過(guò)在 SecurityConfig 上添加 @EnableWeb-Security 注解状植,我們實(shí)際上間接創(chuàng)建了一個(gè) WebSecurityConfiguration Bean津畸。所以在自動(dòng)
配置時(shí),這個(gè)Bean就已經(jīng)存在了吩案, @ConditionalOnMissingBean 條件不成立帝簇, SpringBoot-WebSecurityConfiguration 提供的配置就被跳過(guò)了。
雖然Spring Boot的自動(dòng)配置和 @ConditionalOnMissingBean 讓你能顯式地覆蓋那些可以自動(dòng)配置的Bean丧肴,但并不是每次都要做到這種程度芋浮。讓我們來(lái)看看怎么通過(guò)設(shè)置幾個(gè)簡(jiǎn)單的配置屬性調(diào)整自動(dòng)配置組件吧。

通過(guò)屬性文件外置配置

在處理應(yīng)用安全時(shí)镇草,你當(dāng)然會(huì)希望完全掌控所有配置瘤旨。不過(guò),為了微調(diào)一些細(xì)節(jié)因宇,比如改改端口號(hào)和日志級(jí)別,便放棄自動(dòng)配置察滑,這是一件讓人羞愧的事贺辰。為了設(shè)置數(shù)據(jù)庫(kù)URL,是配置一個(gè)屬性簡(jiǎn)單魂爪,還是完整地聲明一個(gè)數(shù)據(jù)源的Bean簡(jiǎn)單滓侍?答案不言自明,不是嗎捺球?事實(shí)上夕冲,Spring Boot自動(dòng)配置的Bean提供了300多個(gè)用于微調(diào)的屬性。當(dāng)你調(diào)整設(shè)置時(shí)泣栈,只要在環(huán)境變量弥姻、Java系統(tǒng)屬性、JNDI(Java Naming and Directory Interface)疼进、命令行參數(shù)或者屬性文件里進(jìn)行指定就好了

  • 比如springboot程序開(kāi)啟時(shí)候會(huì)有一個(gè)banner就是一個(gè)圖形化的代碼出現(xiàn)秧廉,如果你想要禁用的話,就在application.properties文件里面加上配置:spring.main.show-banner=false嚼锄,當(dāng)然如果你喜歡的話蔽豺,也可以創(chuàng)建名為application.yml的YAML文件:
spring:
  main:
    show-banner: false
  • 比如你想要修改tomcat的端口號(hào):
server:
  port: 8000
  • 要設(shè)置日志級(jí)別茫虽,你可以創(chuàng)建以 logging.level 開(kāi)頭的屬性,后面是要日志名稱濒析。如果根日志級(jí)別要設(shè)置為 WARN 号杏,但Spring Security的日志要用 DEBUG 級(jí)別,可以在application.yml里加入
logging:
    path: /var/logs/
    file: BookWorm.log
    level:
        root: WARN
        org:
          springframework:
            security: DEBUG

另外主经,你也可以把Spring Security的包名寫(xiě)成一行:

logging:
  level:
    root: WARN
      org.springframework.security: DEBUG
  • 配置數(shù)據(jù)源
spring:
    datasource:
        url: jdbc:mysql://localhost/readinglist
        username: dbuser
        password: dbpass
        driver-class-name: com.mysql.jdbc.Driver

以下內(nèi)容:
實(shí)際上庭惜,Spring Boot應(yīng)用程序有多種設(shè)置途徑。Spring Boot能從多種屬性源獲得屬性惠遏,包括如下幾處骏啰。
(1) 命令行參數(shù)
(2) java:comp/env 里的JNDI屬性
(3) JVM系統(tǒng)屬性
(4) 操作系統(tǒng)環(huán)境變量
(5) 隨機(jī)生成的帶 random.* 前綴的屬性(在設(shè)置其他屬性時(shí)判耕,可以引用它們,比如 ${random.long} )
(6) 應(yīng)用程序以外的application.properties或者appliaction.yml文件
(7) 打包在應(yīng)用程序內(nèi)的application.properties或者appliaction.yml文件
(8) 通過(guò) @PropertySource 標(biāo)注的屬性源
(9) 默認(rèn)屬性
這個(gè)列表按照優(yōu)先級(jí)排序帚豪,也就是說(shuō)请毛,任何在高優(yōu)先級(jí)屬性源里設(shè)置的屬性都會(huì)覆蓋低優(yōu)先級(jí)的相同屬性。例如固棚,命令行參數(shù)會(huì)覆蓋其他屬性源里的屬性仙蚜。application.properties和application.yml文件能放在以下四個(gè)位置。
(1) 外置呜师,在相對(duì)于應(yīng)用程序運(yùn)行目錄的/config子目錄里贾节。
(2) 外置衷畦,在應(yīng)用程序運(yùn)行的目錄里祈争。
(3) 內(nèi)置角寸,在config包內(nèi)。
(4) 內(nèi)置沮峡,在Classpath根目錄亿柑。

應(yīng)用程序 Bean 的配置外置

@RequestMapping("/")
@ConfigurationProperties(prefix="amazon")
public class ReadingListController {
    private String associateId;
    private ReadingListRepository readingListRepository;
    @Autowired
    public ReadingListController(
        ReadingListRepository readingListRepository) {
        this.readingListRepository = readingListRepository;
    }
    public void setAssociateId(String associateId) {
      this.associateId = associateId;
    }

如你所見(jiàn), ReadingListController 現(xiàn)在有了一個(gè) associateId 屬性秘症,還有對(duì)應(yīng)的 setAssociateId() 方法式矫,用它可以設(shè)置該屬性采转。 readersBooks() 現(xiàn)在能通過(guò) amazonID 這個(gè)鍵把a(bǔ)ssociateId 的值放入模型。
棒極了板熊!現(xiàn)在就剩一個(gè)問(wèn)題了——從哪里能取到 associateId 的值察绷。
請(qǐng)注意, ReadingListController 上加了 @ConfigurationProperties 注解容劳,這說(shuō)明該Bean的屬性應(yīng)該是(通過(guò)setter方法)從配置屬性值注入的闸度。說(shuō)得更具體一點(diǎn), prefix 屬性說(shuō)明ReadingListController 應(yīng)該注入帶 amazon 前綴的屬性留量。
綜合起來(lái),我們指定 ReadingListController 的屬性應(yīng)該從帶 amazon 前綴的配置屬性中進(jìn)行注入忆绰。 ReadingListController 只有一個(gè)setter方法可岂,就是設(shè)置 associateId 屬性用的setter方法。因此,設(shè)置Amazon Associate ID唯一要做的就是添加 amazon.associateId 屬性致开,把它加入支持的任一屬性源位置里即可萎馅。
在application.yml里設(shè)置:

amazon:
  associateId: habuma-20

在一個(gè)類(lèi)里收集屬性

雖然在 ReadingListController 上加上 @ConfigurationProperties 注解跑起來(lái)沒(méi)問(wèn)題,但這并不是一個(gè)理想的方案飒货。 ReadingListController 和Amazon沒(méi)什么關(guān)系峭竣,但屬性的前綴卻是 amazon 皆撩,這看起來(lái)難道不奇怪嗎?再說(shuō)扛吞,后續(xù)的各種功能可能需要在 ReadingListController 里新增配置屬性滥比,而它們和Amazon無(wú)關(guān)。
與其在 ReadingListController 里加載配置屬性濒持,還不如創(chuàng)建一個(gè)單獨(dú)的Bean寺滚,為它加上@ConfigurationProperties 注解,讓這個(gè)Bean收集所有配置屬性玛迄。代碼清單3-5里的 Amazon-Properties 就是一個(gè)例子,它用于加載Amazon相關(guān)的配置屬性虏杰。

@Component
@ConfigurationProperties("amazon")
public class AmazonProperties {
private String associateId;
    public void setAssociateId(String associateId) {
        this.associateId = associateId;
    }
    public String getAssociateId() {
        return associateId;
    }
}

有了加載 amazon.associateId 配置屬性的 AmazonProperties 后,我們可以調(diào)整
ReadingListController (如代碼清單3-6所示)瘸彤,讓它從注入的 AmazonProperties 中獲取
Amazon Associate ID笛钝。

使用 Profile 進(jìn)行配置

當(dāng)應(yīng)用程序需要部署到不同的運(yùn)行環(huán)境時(shí),一些配置細(xì)節(jié)通常會(huì)有所不同结榄。比如囤捻,數(shù)據(jù)庫(kù)連接的細(xì)節(jié)在開(kāi)發(fā)環(huán)境下和測(cè)試環(huán)境下就會(huì)不一樣蝎土,在生產(chǎn)環(huán)境下又不一樣。Spring Framework從Spring 3.1開(kāi)始支持基于Profile的配置挡毅。Profile是一種條件化配置暴构,基于運(yùn)行時(shí)激活的Profile,會(huì)使用或者忽略不同的Bean或配置類(lèi)庆械。

@Profile("production")
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
}

這里用的 @Profile 注解要求運(yùn)行時(shí)激活 production Profile菌赖,這樣才能應(yīng)用該配置琉用。如果production Profile沒(méi)有激活,就會(huì)忽略該配置奴紧,而此時(shí)缺少其他用于覆蓋的安全配置晶丘,于是應(yīng)用自動(dòng)配置的安全配置唐含。
向application.yml里添加 spring.profiles.active 屬性:

spring:
  profiles:
    active: production

使用多Profile YAML文件進(jìn)行配置

如果使用YAML來(lái)配置屬性捷枯,則可以遵循與配置文件相同的命名規(guī)范专执,即創(chuàng)建application-{profile}.yml這樣的YAML文件,并將與Profile無(wú)關(guān)的屬性繼續(xù)放在application.yml里攀痊。但既然用了YAML拄显,你就可以把所有Profile的配置屬性都放在一個(gè)application.yml文件里凿叠。舉例來(lái)說(shuō)嚼吞,我們可以像下面這樣聲明日志配置:

logging:
level:
root: INFO
---
spring:
  profiles: development
  logging:
  level:
  root: DEBUG
---
spring:
  profiles: production
  logging:
  path: /tmp/
  file: BookWorm.log
  level:
  root: WARN
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末舱禽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子翔始,更是在濱河造成了極大的恐慌里伯,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脖镀,死亡現(xiàn)場(chǎng)離奇詭異狼电,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)强窖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)翅溺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人窿撬,你說(shuō)我怎么就攤上這事叙凡。” “怎么了跛璧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵追城,是天一觀的道長(zhǎng)燥撞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)色洞,這世上最難降的妖魔是什么冠胯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任荠察,我火速辦了婚禮,結(jié)果婚禮上盯荤,老公的妹妹穿的比我還像新娘焕盟。我一直安慰自己京髓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布芥玉。 她就那樣靜靜地躺著备图,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抠藕。 梳的紋絲不亂的頭發(fā)上饿肺,一...
    開(kāi)封第一講書(shū)人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音盾似,去河邊找鬼敬辣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛零院,可吹牛的內(nèi)容都是我干的溉跃。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼告抄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼撰茎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起打洼,我...
    開(kāi)封第一講書(shū)人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎募疮,沒(méi)想到半個(gè)月后炫惩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酝锅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年诡必,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奢方。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搔扁。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蟋字,靈堂內(nèi)的尸體忽然破棺而出稿蹲,到底是詐尸還是另有隱情,我是刑警寧澤鹊奖,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布苛聘,位于F島的核電站,受9級(jí)特大地震影響忠聚,放射性物質(zhì)發(fā)生泄漏设哗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一两蟀、第九天 我趴在偏房一處隱蔽的房頂上張望网梢。 院中可真熱鬧,春花似錦赂毯、人聲如沸战虏。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)烦感。三九已至巡社,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間手趣,已是汗流浹背晌该。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留回懦,地道東北人气笙。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像怯晕,于是被迫代替她去往敵國(guó)和親潜圃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

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