Spring Boot(二)Spring Boot 的配置

一.關於Spring Boot的配置

Spring Boot 對於開發人員最大的好處在於能夠對 Spring 應用進行自動配置。Spring Boot 會根據應用中聲明的第三方依賴來自動配置 Spring 框架,而不須要進行顯式的聲明。好比當聲明瞭對 HSQLDB 的依賴時,Spring Boot 會自動配置成使用 HSQLDB 進行數據庫操做。
Spring Boot 的自動配置功能是沒有侵入性的,只是做爲一種基本的默認實現。開發人員能夠經過定義其餘配置 bean 來替代自動配置所提供的功能(使用@Configuration註解)。好比當應用中定義了本身的數據源 bean 時,自動配置所提供的 HSQLDB 就不會生效。這給予了開發人員很大的靈活性,既能夠快速的建立一個能夠當即運行的原型應用,又能夠不斷的修改和調整以適應應用開發在不一樣階段的須要。Spring Boot 使得這樣的切換變得很簡單。java

注意,自動配置永遠是第二位的,一旦你配置本身的東西,那自動配置的就會被覆蓋。mysql

Spring Boot如何處理多配置

在應用中管理配置並非一個容易的任務,尤爲是在應用須要部署到多個環境中時。一般會須要爲每一個環境提供一個對應的屬性文件,用來配置各自的數據庫鏈接信息、服務器信息和第三方服務帳號等。一般的應用部署會包含開發、測試和生產等若干個環境。不一樣的環境之間的配置存在覆蓋關係。Spring Boot 提供了一種統一的方式來管理應用的配置,容許開發人員使用屬性文件、YAML 文件、環境變量和命令行參數來定義優先級不一樣的配置值。
Spring Boot 所提供的配置優先級順序比較複雜。按照優先級從高到低的順序,具體的列表以下所示。git

  1. 命令行參數。
  2. 經過 System.getProperties() 獲取的 Java 系統參數。
  3. 操做系統環境變量。
  4. 從 java:comp/env 獲得的 JNDI 屬性。
  5. 經過 RandomValuePropertySource 生成的1random.*1屬性。
  6. 應用 Jar 文件以外的屬性文件。
  7. 應用 Jar 文件內部的屬性文件。
  8. 在應用配置 Java 類(包含@Configuration註解的 Java 類)中經過@PropertySource註解聲明的屬性文件。
  9. 經過SpringApplication.setDefaultProperties聲明的默認屬性。

Spring Boot 的這個配置優先級看似複雜,實際上是很合理的。好比命令行參數的優先級被設置爲最高。這樣的好處是能夠在測試或生產環境中快速地修改配置參數值,而不須要從新打包和部署應用。github

SpringApplication 類默認會把以「--」開頭的命令行參數轉化成應用中可使用的配置參數,如 「--name=Alex」 會設置配置參數 「name」 的值爲 「Alex」。好比在啓動一個Spring Boot項目的時候使用java -jar ${項目名}.jar --server.port=9090命令,則該項目的端口就被設置成了9090.web

二.屬性(properties)文件配置

屬性文件是最多見的管理配置屬性的方式。Spring Boot 提供的 SpringApplication 類會搜索並加載 application.properties 文件來獲取配置屬性值。SpringApplication 類會在下面位置搜索該文件。spring

* 當前目錄的「/config」子目錄。
* 當前目錄。
* classpath 中的「/config」包。
* classpath

上面的順序也表示了該位置上包含的屬性文件的優先級。優先級按照從高到低的順序排列。sql

對於配置屬性,能夠在代碼中經過「@Value」註解來使用,這點和普通的Spring項目同樣。以下例:
建立一個SpringBoot的Maven項目,項目結構以下:數據庫

圖片描述

pom.xml文件中引入Spring Boot Parent和Spring Boot Web的依賴:springboot

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
        <relativePath/> 
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.0</version>
        </dependency>
    </dependencies>

在resources目錄下建立一個名爲application.properties 的文件,將以下內容添加至該文件:服務器

book.name=HongLouMeng
book.author=曹雪芹
book.publisher=\u4e09\u8054\u51fa\u7248\u793e
book.price=68.5

建立啓動類:

package com.ddcx.springboot.democonfig;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConfigDemoApplication {

    public static void main(String[] args) {
        //讀取默認配置文件的啓動方式
        SpringApplication.run(ConfigDemoApplication.class, args);

    }
}

再建立一個controller類,在這個類中就能夠經過@Value從配置文件中獲取配置好的值:

package com.ddcx.springboot.democonfig.controller;

import com.ddcx.springboot.democonfig.entity.Book;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class DemoController {

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

    @Value("${book.author}")
    private String bookAuthor;

    @Value("${book.publisher}")
    private String publisher;

    @Value("${book.price}")
    private String price;

    @RequestMapping("/bookInfo")
    String bookInfo() {
        return "bookName-->" + bookName + "\nbookAuthor-->" + bookAuthor +
                "\npublisher-->" + publisher + "\nprice-->" + price ;
    }

}



在postman中發送請求獲得以下結果:

圖片描述

properties文件中的中文出現了亂碼問題,能夠在properties文件中改用unicode編碼的方式。

除此以外,還能夠配置服務器端口、數據庫等各類配置:

# 配置服務器端口爲8090
server.port=8090
# 配置應用的根路徑,必須以'/'開頭,不然會報異常:
# java.lang.IllegalArgumentException: ContextPath must start with '/ and not end with '/'
server.context-path=/demo-config

除了使用@Value註解綁定配置屬性值以外,還可使用@ConfigurationProperties(prefix="book")註解,配置屬性中以「book」爲前綴的屬性值會被自動綁定到 Java 類中同名的屬性上,前提是要有屬性的set方法。這種方法能夠方便地配置數據庫。

在這個示例中好比建立一個Book類:

package com.ddcx.springboot.democonfig.entity;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@Component  //由於要使用自動注入,因此要掃描註冊到ioc容器中
@ConfigurationProperties(prefix="book")
public class Book {

    private String name;
    private String author;
    private String publisher;
    private double price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

在前面縮寫的DemoController中自動注入一個Book屬性,添加以下代碼:

private static Gson gson = new Gson();
@Autowired
private Book book;

@RequestMapping("/prefixConfigTest")
String prefixConfigTest() {
    return gson.toJson(book);
}

在postman中測試代表也能夠獲取到application.properties中的配置,而且服務器的端口配置也能夠同時獲得驗證:

圖片描述

SpringBoot 如何更改默認配置文件的名稱

前面講到,默認狀況下SpringBoot 會去指定的路徑下搜索文件名稱爲 application.yml、application.properties的配置文件,那如何本身定義配置文件名?

在SpringBoot中能夠經過「spring.config.name」配置屬性來指定不一樣的屬性文件名稱。也能夠經過「spring.config.location」來添加額外的屬性文件的搜索路徑。若是應用中包含多個 profile,能夠爲每一個 profile 定義各自的屬性文件,按照「application-{profile}」來命名。

接下來能夠實際操做一下,首先在resources目錄下再建立一個 springboot-config.properties 的文件,
並在配置文件中添加內容:

book.name=Effective Java
book.author=Joshua Bloch


server.port=8070

在將啓動類的啓動方式改爲以下:

package com.ddcx.springboot.democonfig;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;

@SpringBootApplication
public class ConfigDemoApplication {

   public static void main(String[] args) {
      //讀取默認配置文件的啓動方式
      //SpringApplication.run(ConfigDemoApplication.class, args);
      
      //讀取自定義配置文件名的啓動方式
      new SpringApplicationBuilder(ConfigDemoApplication.class)
            .properties("spring.config.location=classpath:/springboot-config.properties")
            .run(args);
   }
}

訪問結果:

圖片描述

這裏會有一個現象,若是 application.properties 和 springboot-config.properties 兩個文件同時存在,當application.properties中的配置在pringboot-config.properties也一樣配置了,好比上面的bookName,那麼pringboot-config.properties中的配置優先級更高,當application.properties中的配置在pringboot-config.properties沒有配置,那麼application.properties中的那項配置仍然會起做用,好比上面的publisher和server.context-path等。可是若是將 application.properties文件名改爲其它的,好比 application-config.properties,則徹底以pringboot-config.properties這個配置文件爲準。


三.YAML配置文件

除了屬性文件,SpringApplication 類也提供了對 YAML 配置文件的支持,下面給出了 application.yml 文件的示例。

注意:使用.yml時,屬性名的值和冒號中間必須有空格,如branch: master正確,branch:master就是錯的。

user:
  username: 張三
  age: 22
  contactAddress[0]:
    province: hunan
    city: changsha
    area: yuhuaqu
  contactAddress[1]:
      province: guangdong
      city: guangzhou
      area: tianhequ

SpringBoot的配置支持嵌套和幾何配置,對於上面的配置,對應以下User和Address兩個類:

package demoyaml.entity;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

/**
* Created by liaosi on 2017/10/7.
*/
@Component
@ConfigurationProperties(prefix = "user")
public class User {

    private String username;
    private Integer age;
    private List<Address> contactAddress;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public List<Address> getContactAddress() {
        return contactAddress;
    }

    public void setContactAddress(List<Address> contactAddress) {
        this.contactAddress = contactAddress;
    }
}
package demoyaml.entity;

/**
* Created by liaosi on 2017/10/7.
*/
public class Address {

    private String province;
    private String city;
    private String area;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getArea() {
        return area;
    }

    public void setArea(String area) {
        this.area = area;
    }
}

在Controller中添加訪問這個配置的user對象的方法:

package demoyaml.controller;


import com.google.gson.Gson;
import demoyaml.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class DemoController {

    private static Gson gson = new Gson();
    @Autowired
    private User user;


    @RequestMapping("/getUser")
    String getUser() {
        return gson.toJson(user);
    }

}

訪問結果:

圖片描述

四.多環境配置

在實際開發中,一般會有開發、測試、生產等多種環境,SpringBoot是怎麼來配置多種環境的呢?

1.properties多環境配置

(1)在項目中添加不一樣環境的配置文件

圖片描述

(2)在application.properties配置文件中配置須要激活那個環境:

#激活哪個環境的配置文件
spring.profiles.active=dev
#公共配置
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss:

2.yaml多環境配置

在application中增長內容:

#激活哪個環境的配置文件
spring:
    profiles:
        active: development
---
spring:
    profiles: development
    db:
        url: jdbc:hsqldb:file:testdb
        username: dev
        password: dev
#在配置文件增長三個短橫線區分不一樣的環境
---
spring:
    profiles: test
    db:
        url: jdbc:mysql://localhost/test
        username: test
        password: test

定義一個DBConfig類,獲取激活的那個環境的配置:

package demoyaml.entity;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@Component
@ConfigurationProperties(prefix = "db")
public class DBConfig {

    private String url;
    private String username;
    private String password;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

經過controller中的方法查看:

package demoyaml.controller;


import com.google.gson.Gson;
import demoyaml.entity.DBConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class DemoController {

    private static Gson gson = new Gson();

    @Autowired
    private DBConfig DBConfig;

    @RequestMapping("/getEnvConfig")
    String getDBConfig() {
        return gson.toJson(DBConfig);
    }

}

圖片描述

3.兩種配置方式的比較

* Properties配置多環境,須要添加多個配置文件,YAML只須要一個配件文件
* 書寫格式的差別,yaml相對比較簡潔,優雅
* YAML的缺點:不能經過@PropertySource註解加載。若是須要使用@PropertySource註解的方式加載值,那就要使用properties文件。

本節示例代碼已上傳到github: https://github.com/liaosilzu2...

相關文章
相關標籤/搜索