SpringBoot(1)

以SpringBoot官方文檔為原型,闡述SpringBoot。僅供學(xué)習(xí)參考,如有錯漏之處,望多包涵。

1.Spring Boot 入門

1.1 構(gòu)建SpringBoot項目

構(gòu)建springboot的方法有很多,如:maven\gradle\springboot-cli等。
介紹一下我常用的方法:
1、使用IDEA new->project



2、選擇 spring Initializr(spring初始化),設(shè)置JDK,一路next



3、選擇初始化導(dǎo)入的依賴,按需選擇

4、finished,喝杯咖啡等IDEA下載依賴就好了。

1.2. 包結(jié)構(gòu)規(guī)范

經(jīng)典的包結(jié)構(gòu):

com
 +- example
     +- myapplication
         +- Application.java
         |
         +- customer
         |   +- Customer.java
         |   +- CustomerController.java
         |   +- CustomerService.java
         |   +- CustomerRepository.java
         |
         +- order
             +- Order.java
             +- OrderController.java
             +- OrderService.java
             +- OrderRepository.java

強烈推薦將主應(yīng)用類放在其它類之上的根包中。如果您的主類在根包中,可以使用@SpringBootApplication 注解,它隱式定義了某些項目的包搜索的基準(zhǔn)起點。當(dāng)然,你也可以通過設(shè)置屬性,自定義掃描包的范圍。
提示

  • @SpringBootApplication = (默認屬性)@Configuration + @EnableAutoConfiguration + @ComponentScan。

1.3. 配置類

1.3.1. 導(dǎo)入額外的配置類

SpringBoot不推薦使用XML配置,額外的配置類可以通過@Import導(dǎo)入,或者可以在@ComponentScan的掃描范圍內(nèi),添加@Configuration類。

1.3.2. 禁用指定的自動配置類

SpringBoot有一套默認的自動配置類,如果你發(fā)現(xiàn)不需要指定的配置類,可以通過使用 @EnableAutoConfigurationexclude 屬性來禁用它們。

@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}

如果類不在 classpath 下,您可以使用注解的excludeName 屬性并指定完全類名。最后,您還可以通過 spring.autoconfigure.exclude property 控制要排除的自動配置類列表。

1.4.Spring Bean與依賴注入

如果您按照上述最佳實踐(將應(yīng)用類放在根包中)來組織代碼,則可以添加無參的 @ComponentScan。所有應(yīng)用組件(@Component、@Service、@Repository、@Controller 等)將自動注冊為 Spring Bean。
如何獲取Spring Bean?
通常使用@Autowired獲取Bean。

@Component
public class DatabaseAccountController {

    @Autowired
    private RiskAssessService riskAssessService;

    // ...
}

如果說一個項目出現(xiàn)了相同名字的Bean,那么就要給其中一個設(shè)置另外的name,@Autowired結(jié)合@Qualifier獲取。

@Component
public class DatabaseAccountController {

    @Autowired
    @Qualifier("RAssessService")
    private RiskAssessService riskAssessService;

    // ...
}

@Service("RAssessService")
public class RiskAssessService {
    // ...
}

也可以通過構(gòu)造注入所需Bean。

@Service
public class RiskAssessService  {

   private final RiskAssessor riskAssessor;

   @Autowired
   public DatabaseAccountService(RiskAssessor riskAssessor) {
       this.riskAssessor = riskAssessor;
   }

   // ...
}

提示

  • 如果 bean 中只有一個構(gòu)造方法,您可以忽略掉 @Autowired 注解。
  • 構(gòu)造注入允許 riskAssessor 字段被修飾為 final,這表示以后它不能被更改

1.5.運行你的應(yīng)用

在您使用IDEA或Eclipse,Maven構(gòu)建項目的前提下,您可以通過開發(fā)工具輕松運行您的應(yīng)用。您也可以通過命令行運行應(yīng)用。例如:

$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar

提示

  • target指向您項目的路徑。
  • myapplication-0.0.1-SNAPSHOT.jar是您打包應(yīng)用的名稱。您可以通過mvn package命令行打包應(yīng)用。

也可以在運行打包應(yīng)用程序時開啟遠程調(diào)試支持。該功能允許您將調(diào)試器附加到打包的應(yīng)用中。

$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
       -jar target/myapplication-0.0.1-SNAPSHOT.jar

使用maven插件。

mvn spring-boot:run    

1.6.熱插拔

java應(yīng)用熱插拔,即JVM熱插拔,應(yīng)用更新不需要重啟就能獲得相應(yīng)的效果。JVM 熱插拔在可替換字節(jié)碼方面有所限制。想要更完整的解決方案,可以使用 JRebel。

1.7.spring-boot-devtools

詳情參考開發(fā)者工具


2. Spring Boot的特性

2.1. 自定義SpringApplication

如果您想自定義SpringBoot應(yīng)用的初始化配置,您可以創(chuàng)建本地實例定制化。例如,關(guān)閉banner:

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(MySpringConfiguration.class);
    app.setBannerMode(Banner.Mode.OFF);
    app.run(args);
}

或者,優(yōu)雅的使用流式構(gòu)建器API(Fluent Builder API),

new SpringApplicationBuilder()
        .sources(Parent.class)
        .child(Application.class)
        .bannerMode(Banner.Mode.OFF)
        .run(args);

也可以使用 application.properties 文件外部化配置。
關(guān)于配置選項的完整列表,請參閱 SpringApplication Javadoc。
關(guān)于SpringApplicationBuilder詳細信息,請參閱 SpringApplicationBuilder Javadoc。

2.2. 自定義banner

banner文件是用來定義應(yīng)用啟動日志輸出的。在 classpath 下添加一個 banner.txt 文件,或者將 spring.banner.location 屬性指向該文件的位置來更改啟動時打印的 banner。如果文件采用了非 UTF-8 編碼,您可以設(shè)置 spring.banner.charset 來解決。除了文本文件,您還可以將 banner.gif、banner.jpg 或者 banner.png 圖片文件添加到 classpath 下,或者設(shè)置 spring.banner.image.location 屬性。指定的圖片將會被轉(zhuǎn)換成 ASCII 形式并打印在 banner 文本上方。

您可以在 banner.txt 文件中使用以下占位符:

變量 描述
${application.version} 您的應(yīng)用版本號,聲明在 MANIFEST.MF 中。例如,Implementation-Version: 1.0 將被打印為 1.0
${application.formatted-version} 您的應(yīng)用版本號,聲明在 MANIFEST.MF 中,格式化之后打?。ㄓ美ㄌ柪ㄆ饋恚?v 為前綴),例如 (v1.0)。
${spring-boot.version} 您使用的 Spring Boot 版本。例如 2.1.1.RELEASE.。
${spring-boot.formatted-version} 您使用的 Spring Boot 版本格式化之后顯示(用括號括起來,以 v 為前綴)。例如 (v2.1.1.RELEASE)。
${Ansi.NAME}(或 ${AnsiColor.NAME}、${AnsiBackground.NAME}、${AnsiStyle.NAME} 其中 NAME 是 ANSI 轉(zhuǎn)義碼的名稱。有關(guān)詳細信息,請參閱 AnsiPropertySource。
${application.title} 您的應(yīng)用標(biāo)題,聲明在 MANIFEST.MF 中,例如 Implementation-Title: MyApp 打印為 MyApp。

注意

  • 如果您想以編程的方式生成 banner,可以使用 SpringApplication.setBanner(?...) 方法。使用 org.springframework.boot.Banner 接口并實現(xiàn)自己的 printBanner() 方法。打印的 banner 被注冊名為 springBootBanner 的單例 bean。
  • 您還可以使用 spring.main.banner-mode 屬性來確定是否必須在 System.out(console)上打印 banner,還是使用日志記錄器(log)或者都不打?。╫ff)。YAML 將 off 映射為 false,因此如果要禁用應(yīng)用程序 banner,請確保屬性添加引號。
spring:
    main:
        banner-mode: "off"

2.3. 應(yīng)用事件與監(jiān)聽器

Spring Framework事件都繼承了抽象類 org.springframework.context.ApplicationEvent,諸如:ContextRefreshedEvent等。
注意

ApplicationContext 創(chuàng)建之前,實際上觸發(fā)了一些事件,因此您不能像 @Bean 一樣注冊監(jiān)聽器。您可以通過 SpringApplication.addListeners(?...) 或者 SpringApplicationBuilder.listeners(...?) 方法注冊它們。如果您希望無論應(yīng)用使用何種創(chuàng)建方式都能自動注冊這些監(jiān)聽器,您都可以將 META-INF/spring.factories 文件添加到項目中,并使用 org.springframework.context.ApplicationListener 屬性鍵指向您的監(jiān)聽器。比如:org.springframework.context.ApplicationListener=com.example.project.MyListener。

當(dāng)您運行應(yīng)用時,應(yīng)用程序事件將按照以下順序發(fā)送:

  1. 在開始應(yīng)用開始運行但還沒有進行任何處理時(除了注冊監(jiān)聽器和初始化器[initializer]),將發(fā)送 ApplicationStartingEvent。
  2. 當(dāng) Environment 被上下文使用,但是在上下文創(chuàng)建之前,將發(fā)送 ApplicationEnvironmentPreparedEvent。
  3. 在開始刷新之前,bean 定義被加載之后發(fā)送 ApplicationPreparedEvent。
  4. 在上下文刷新之后且所有的應(yīng)用和命令行運行器(command-line runner)被調(diào)用之前發(fā)送 ApplicationStartedEvent。
  5. 在應(yīng)用程序和命令行運行器(command-line runner)被調(diào)用之后,將發(fā)出 ApplicationReadyEvent,該事件用于通知應(yīng)用已經(jīng)準(zhǔn)備處理請求。
  6. 如果啟動時發(fā)生異常,將發(fā)送 ApplicationFailedEvent。

應(yīng)用程序事件發(fā)送使用了 Spring Framework 的事件發(fā)布機制。該部分機制確保在子上下文中發(fā)布給監(jiān)聽器的事件也會發(fā)布給所有祖先上下文中的監(jiān)聽器。因此,如果您的應(yīng)用程序使用有層級結(jié)構(gòu)的 SpringApplication 實例,則監(jiān)聽器可能會收到同種類型應(yīng)用程序事件的多個實例。

為了讓監(jiān)聽器能夠區(qū)分其上下文事件和后代上下文事件,您應(yīng)該注入其應(yīng)用程序上下文,然后將注入的上下文與事件的上下文進行比較??梢酝ㄟ^實現(xiàn) ApplicationContextAware 來注入上下文,如果監(jiān)聽器是 bean,則使用 @Autowired 注入上下文。

提示

您可能不會經(jīng)常使用應(yīng)用程序事件,但了解他們的存在還是很有必要的。在框架內(nèi)部,Spring Boot 使用這些事件來處理各種任務(wù)。

2.4.外部化配置

為了適配多環(huán)境的部署。Spring Boot可以通過properties 文件、YAML 文件、環(huán)境變量或者命令行參數(shù)來外部化配置??梢允褂?@Value 注解將屬性值直接注入到 bean 中,可通過 Spring 的 Environment 訪問,或者通過 @ConfigurationProperties 綁定到結(jié)構(gòu)化對象。

Spring Boot使用了PropertySource指令,由于智能覆蓋默認值。屬性值將按照以下順序加載:

  1. 在您的主目錄(當(dāng) devtools 被激活,則為 ~/.spring-boot-devtools.properties )中的 Devtools 全局設(shè)置屬性。
  2. 在測試中使用到的 @TestPropertySource 注解。
  3. 在測試中使用到的 properties 屬性,可以是 @SpringBootTest 和用于測試應(yīng)用程序某部分的測試注解。
  4. 命令行參數(shù)。
  5. 來自 SPRING_APPLICATION_JSON 的屬性(嵌入在環(huán)境變量或者系統(tǒng)屬性【system propert】中的內(nèi)聯(lián) JSON)。
  6. ServletConfig 初始化參數(shù)。
  7. ServletContext 初始化參數(shù)。
  8. 來自 java:comp/env 的 JNDI 屬性。
  9. Java 系統(tǒng)屬性(System.getProperties())。
  10. 操作系統(tǒng)環(huán)境變量。
  11. 只有 random.* 屬性的 RandomValuePropertySource。
  12. 在已打包的 jar 外部的指定 profile 的應(yīng)用屬性文件(application-{profile}.properties 和 YAML 變量)。
  13. 在已打包的 jar 內(nèi)部的指定 profile 的應(yīng)用屬性文件(application-{profile}.properties 和 YAML 變量)。
  14. 在已打包的 jar 外部的應(yīng)用屬性文件(application.properties 和 YAML 變量)。
  15. 在已打包的 jar 內(nèi)部的應(yīng)用屬性文件(application.properties 和 YAML 變量)。
  16. @Configuration 類上的 @PropertySource 注解。
  17. 默認屬性(使用 SpringApplication.setDefaultProperties 指定)。

2.4.1. 配置隨機值

RandomValuePropertySource 對于隨機值注入非常有用(比如在保密場景或者測試用例中)。它可以產(chǎn)生 integer、long、uuid 和 string。如下示例:

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

2.4.2. 訪問命令行屬性

默認情況下,SpringApplication 將所有命令行選項參數(shù)(即以 -- 開頭的參數(shù),比如 --server.port=9000)轉(zhuǎn)換為屬性,并將它們添加到 Spring Environment 中。如之前所述,命令行屬性始終優(yōu)先于其他屬性源。

如果您不希望將命令行屬性添加到 Environment,可以使用 SpringApplication.setAddCommandLineProperties(false)來禁用它們。

2.4.3. 應(yīng)用程序?qū)傩晕募?/h4>

SpringApplication 從以下位置的 application.properties 文件中加載屬性(properties),并將它們添加到 Spring Environment 中:

  1. 當(dāng)前目錄/config 子目錄
  2. 當(dāng)前目錄
  3. classpath 上的 /config 包
  4. classpath 根路徑
    列表按序號優(yōu)先級排序,序號越小,優(yōu)先級越高。
    用于多環(huán)境配置,如下圖:



    如果您不喜歡 application.properties 作為配置文件名,則可以通過指定 spring.config.name 環(huán)境屬性來切換到另一個文件名。您還可以使用 spring.config.location 環(huán)境屬性來引用一個顯式位置(以逗號分隔的目錄位置或文件路徑列表)。以下示例展示了如何指定其他文件名:

$ java -jar myproject.jar --spring.config.name=myproject

以下示例展示了如何指定兩個位置:

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

2.4.3. 屬性文件中的占位符

application.properties 中的值在使用時通過現(xiàn)有的 Environment 進行過濾,因此您可以返回之前定義的值(例如,從系統(tǒng)屬性)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application

2.4.4. 使用 YAML 代替屬性文件

YAML 是 JSON 的超集,是一個可用于指定層級配置數(shù)據(jù)的便捷格式。只要在 classpath 上有 SnakeYAML庫,SpringApplication 類就會自動支持 YAML 作為屬性文件(properties)的替代。
注意

如果使用 starter,則 spring-boot-starter 會自動提供 SnakeYAML。
通常YAML文件后綴名用 .yml。

2.4.4.1. 加載YAML

例如以下文件:

environments:
  dev:
    url: http://dev.example.com
    name: Developer Setup
my:
  servers:
    - dev.example.com
    - another.example.com

轉(zhuǎn)換為以下屬性(properties):

environments.dev.url=http://dev.example.com
environments.dev.name=Developer Setup
my.servers[0]=dev.example.com
my.servers[1]=another.example.com

YAML以行縮進的形式表示層級關(guān)系。

2.4.4.2. 多profile YAML文檔

spring.profiles key 在單個文件中指定多個特定 profile 的 YAML 文檔,以指示文檔何時應(yīng)用,如下所示:

server:
  address: 192.168.1.100
---
spring:
  profiles: development
server:
  address: 127.0.0.1
---
spring:
  profiles: production & eu-central
server:
  address: 192.168.1.120

在前面示例中,如果 development profile 處于激活狀態(tài),則 server.address 屬性得值為 127.0.0.1。 同樣,如果 production 和 eu-central profile 處于激活狀態(tài),則 server.address 屬性的值為 192.168.1.120。如果未激活 development、production 或 eu-central profile,則該屬性的值為 192.168.1.100。
注意

profile 表達式允許表達更復(fù)雜的 profile 邏輯,例如 production & (eu-central | eu-west)。有關(guān)詳細信息,請查閱參考指南。

2.4.4.3. YAML 的缺點

無法使用 @PropertySource 注解加載 YAML 文件。因此,如果您需要以這種方式加載值,請使用屬性文件(properties)。

2.4.5. 類型安全的配置屬性

使用 @Value("${property}") 注解來注入配置屬性有時會很麻煩,特別是如果您使用了多個屬性或者您的數(shù)據(jù)本質(zhì)上是分層結(jié)構(gòu)。Spring Boot 提供了另一種使用屬性的方法,該方法使用強類型的 bean 來管理和驗證應(yīng)用程序的配置,如下所示:

@ConfigurationProperties("acme")
public class AcmeProperties {

    private boolean enabled;

    private InetAddress remoteAddress;

    private final Security security = new Security();

    public boolean isEnabled() { ... }

    public void setEnabled(boolean enabled) { ... }

    public InetAddress getRemoteAddress() { ... }

    public void setRemoteAddress(InetAddress remoteAddress) { ... }

    public Security getSecurity() { ... }

    public static class Security {

        private String username;

        private String password;

        private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

        public String getUsername() { ... }

        public void setUsername(String username) { ... }

        public String getPassword() { ... }

        public void setPassword(String password) { ... }

        public List<String> getRoles() { ... }

        public void setRoles(List<String> roles) { ... }

    }
}

前面的 POJO 定義了以下屬性:

  • acme.enabled,默認值為 false。
  • acme.remote-address,可以從 String 強制轉(zhuǎn)換的類型。
  • acme.security.username,內(nèi)嵌一個 security 對象,其名稱由屬性名稱決定。特別是,返回類型根本沒有使用,可能是 SecurityProperties。
  • acme.security.password
  • acme.security.roles,String 集合。

@Value@ConfigurationProperties 之間的差異

功能 @ConfigurationProperties @Value
寬松綁定
元數(shù)據(jù)支持
SpEL 表達式

同時,不要忘了注冊屬性類,如下所示:

@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}

Bean方式配置屬性,與外部YAML配置,有異曲同工之妙。

# application.yml

acme:
    remote-address: 192.168.1.1
    security:
        username: admin
        roles:
          - USER
          - ADMIN

要使用@ConfigurationProperties bean,您可以使用與其他 bean 相同的方式注入它們,如下所示:

@Service
public class MyService {
  
    @Autowired
    private final AcmeProperties properties;

    //...  
}

提示

使用 @ConfigurationProperties 還可以生成元數(shù)據(jù)文件,IDE 可以通過這些文件來為您自己的 key 提供自動完成功能。有關(guān)詳細信息,請參閱附錄 B:配置元數(shù)據(jù)。

2.4.6. 寬松綁定

Spring Boot 使用一些寬松的規(guī)則將 Environment 屬性綁定到 @ConfigurationProperties bean,因此 Environment 屬性名不需要和 bean 屬性名精確匹配。常見的示例包括使用了 - 符號分割的環(huán)境屬性(例如,context-path 綁定到 contextPath)和大寫環(huán)境屬性(例如,PORT 綁定到 port)。
注意

注解的 prefix 值必須是 kebab (短橫線命名)風(fēng)格(小寫并用 - 分隔,例如 acme.my-project.person)。

表2.4.6.1 每種屬性源(property source)的寬松綁定規(guī)則

屬性源 簡單類型 列表集合類型
properties 文件 駝峰式、短橫線式或下劃線式 標(biāo)準(zhǔn)列表語法使用 [] 或逗號分隔值
YAML 文件 駝峰式、短橫線式或者下劃線式 標(biāo)準(zhǔn) YAML 列表語法或者逗號分隔值
環(huán)境變量 大寫并且以下劃線作為定界符,_ 不能放在屬性名之間使用 數(shù)字值兩邊使用下劃線連接,例如 MY_ACME_1_OTHER = my.acme[1].other
系統(tǒng)屬性 駝峰式、短橫線式或者下劃線式 標(biāo)準(zhǔn)列表語法使用 [] 或逗號分隔值

提示

Spring Boot建議,屬性盡可能以kebab (短橫線命名)風(fēng)格存儲,比如 my.property-name=acme。

未完待續(xù)~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容