不學無數——SpringBoot入門Ⅲ

SpringBoot-外部資源的配置

1.外部資源的配置優先級

爲了可以在不一樣的環境運行不一樣的配置文件,或者有些代碼的一些變量是跟隨着環境的改變而改變的,這時候就須要在外部作一些配置。SpringBoot容許這麼作,而且有一套配置規則。能夠經過@Value註解進行將一些變量動態的取出來。SpringBoot支持多種的外部配置的方式,其中的優先級以下:html

  1. 全局的設置在根目錄中(~/.spring-boot-devtools.propertiesjava

  2. @TestPropertySource在Test模塊中的註解web

  3. @SpringBootTest#properties也是在Test模塊中spring

  4. 命令行json

  5. 命令行中的SPRING_APPLICATION_JSONJSON字符串, 例如java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar數組

  6. ServletConfig 初始化參數,可在代碼進行配置瀏覽器

  7. ServletContext 初始化參數,可在代碼進行配置緩存

  8. 來自java:comp/env的JNDI屬性app

  9. Java系統屬性(System.getProperties()框架

  10. 操做系統的環境變量

  11. RandomValuePropertySource配置的random.*屬性值

  12. jar外部的帶指定profileapplication.yml,好比application-{profile}.yml

  13. jar內部的帶指定profileapplication.yml,好比application-{profile}.yml

  14. jar外部的application.yml

  15. jar內部的application.yml

  16. 在自定義的@Configuration類中定於的@PropertySource

  17. 啓動的main方法中,定義的默認配置。SpringApplication.setDefaultProperties

下面給出具體的實例:

@SpringBootApplication
@RestController
public class FirstSpringBootApplication {

    @Value("${name}")
    private String name;
    
    @RequestMapping("/")
    String home() {
        return name;
    }

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(FirstSpringBootApplication.class);
        app.run(args);
    }
}

能夠在application.yml或者application.properties配置文件中設置name的值

application.yml

name: 不學無數

注意在name: 的冒號後面要加空格

application.properties

name=不學無數

這樣在啓動項目的時候而後訪問http:localhost:8080就能夠取出了name的值

<center><img src="http://p9jfgo4wc.bkt.clouddn.com/buxuewushu.png"/></center>

2.配置隨機值

當想要一些隨機值的時候SpringBoot也提供了一些方法,隨機數具體有哪些應用呢,例如能夠防止瀏覽器認爲是相同的資源而去讀取緩存,或者是生成驗證碼,在application.properties配置以下

my.secret=${random.value} --生成隨機字符串
my.number=${random.int}	  --生成隨機數
my.uuid=${random.uuid}	  --生成uuid
my.number.less.than.ten=${random.int(10)} -- 生成10之內的隨機數
my.number.in.range=${random.int[1024,65536]} --生成1024到65536的隨機數

取出的代碼以下:

@Value("${my.secret}")
    private String secret;
    @Value("${my.number}")
    private String number;
    @Value("${my.uuid}")
    private String uuid;
    @Value("${my.number.less.than.ten}")
    private Integer ten;
    @Value("${my.number.in.range}")
    private Integer range;

    @RequestMapping("/")
    String home() {
        StringBuffer stringBuffer=new StringBuffer();
        stringBuffer.append("my.secret:"+secret+"<br/>");
        stringBuffer.append("my.number:"+number+"<br/>");
        stringBuffer.append("my.uuid:"+uuid+"<br/>");
        stringBuffer.append("my.number.less.than.ten}:"+ten+"<br/>");
        stringBuffer.append("my.number.in.range:"+range+"<br/>");
        return stringBuffer.toString();
    }

而後訪問http:localhost:8080能夠查看到以下的頁面

<center><img src="http://p9jfgo4wc.bkt.clouddn.com/suijishu1.png"/></center>

3.命令行配置

SpingApplication默認的可以轉變任何命令行的參數而後將其配置在Spring中,例如--server.port=9000,那麼web啓動的端口號就變爲了9000。

<center><img src="http://p9jfgo4wc.bkt.clouddn.com/%E7%AB%AF%E5%8F%A3.jpeg"/></center>

而後啓動項目就會發現端口號改變了。

若是不想讓命令行的配置加入到Spring環境中的話,能夠SpringApplication.setAddCommandLineProperties(false)進行設置

4.資源文件配置

SpringApplication會從application.properties進行加載系統的配置,而且將其配置加入到Spring的環境中

你也可使用YAML('.yml')來代替.properties

若是不想使用application.properties做爲配置文件的名字的話,那麼能夠選擇其餘名字的文件做爲配置文件。能夠具體設置spring.config.name環境變量進行設置。也可使用spring.config.location後面跟文件的全路徑名。

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

spring.config.name和spring.config.location這兩個配置由於是要設置哪一個配置文件起做用的,因此必須在程序啓動以前設置,例如設置在系統的環境變量中,或者是設置在啓動的參數中。

5.獨特的配置(Profile-specific Properties)

不知道該怎麼翻譯,就把英文給加在後面了,以避免誤人子弟。在公司進行開發的過程當中,也許咱們會碰到這種狀況,例如在開發環境中用的一套配置,而在測試環境是另外一套的配置。因此在不一樣的環境須要有不一樣的配置文件。SpringBoot也提供了這樣一套的配置規則。application-{profile}.properties。其中的profile]能夠進行配置化,若是沒有配置的話那麼就會以默認的application-default.properties爲配置文件。其中profile的屬性能夠在application.properties進行配置spring.profiles.active的值。 application.properties配置以下

spring.profiles.active=test --即加載application-test.properties

或者spring.profiles.active=dev --即加載application-dev.properties

application-test.properties

name=BuXueWuShu---Test

application-dev.properties

name=BuXueWuShu---Dev

這樣在application.properties中就能夠加載不一樣的配置文件

@Value("${name}")
    private String name;
    @RequestMapping("/")
    String home() {
        return name;
    }

經過不一樣的環境配置就能夠訪問不一樣值

固然你也能夠經過上一節的spring.config.location這個啓動的環境變量進行設置想要啓動的時候加載具體哪一個配置文件

6.資源文件中的佔位符

當在資源文件中定義過一些變量的時候,若是在一樣的資源文件中要複用,那麼也能夠進行引用。

application.properties配置

my.name=BuXueWuShu
my.description=My name is ${my.name}

7.使用YAML

YAML是針對於JSON的一種擴展,因此作配置文件是很是不錯的選擇。而且在SpringApplication中若是你引入了spring-boot-starter的包,那麼SpringApplication會自動的支持YAML。

7.1解析YAML

Spring框架提供了兩個簡便的類可以解析YAML文檔。YamlPropertiesFactoryBean解析YAML做爲Properties。YamlMapFactoryBean解析YAML做爲Map。例以下面的YAML文件中

environments:
	dev:
		url: http://dev.example.com
		name: Developer Setup
	prod:
		url: http://another.example.com
		name: My Cool App

剛纔的例子這個YAML將會被解析成

environments.dev.url=http://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=http://another.example.com
environments.prod.name=My Cool App

YAML列表將會被替代成數組的類型,根據[index]進行取值

my:
servers:
	- dev.example.com
	- another.example.com

上面的例子將會被解析成下面這種形式的

my.servers[0]=dev.example.com
my.servers[1]=another.example.com

若是你想講這些數據進行取出來的話,新建一個配置類,使用SpringBoot提供的@ConfigurationProperties的註解,而後在此類中得有一個List或者Set集合,而後設置get方法就能將值取出來了,具體實現以下:

@ConfigurationProperties(prefix="my")
public class Config {

	private List<String> servers = new ArrayList<String>();

	public List<String> getServers() {
		return this.servers;
	}
}

7.2 多環境配置YAML

在講解application.properties的時候若是想使用多環境的配置那麼就是設置不一樣的application-{profile}.properties的文件具體哪一個文件生效能夠在application.properties中設置spring.profiles.active屬性便可。可是在YAML如何在不一樣的環境中生效呢?固然第一種辦法就是和application.properties同樣設置不一樣的yml文件,而後進行設置具體哪一個生效便可。YAML也有另外一種的方法。以下所示

server:
	address: 192.168.1.100
spring:
	profiles:
		active:在此設置具體哪一個profiles生效便可(例如此處填寫 test) 就是adress就是192.168.1.120
---
spring:
	profiles: development
server:
	address: 127.0.0.1
---
spring:
	profiles: test
server:
	address: 192.168.1.120

經過"---"設置不一樣的環境的配置屬性

若是你在配置文件中沒有設置spring.profiles.active屬性那麼配置文件就不知道哪一個生效,因此他會找一個默認的進行設置。只須要設置spring.profiles:default 便可

server:
  port: 8000
---
spring:
  profiles: default
  security:
    user:
      password: weak

8.經過類型匹配屬性(Type-safe Configuration Properties)

經過@Value("${property}")能夠將配置中的屬性在類中取出來,這樣是能夠的,可是若是有多個類型要取或者是要取的有着嚴格的等級。那麼取的時候會有些麻煩,SpringBoot提供了一套能夠經過類型匹配在類中寫出熟悉而後加載到配置文件中。而這也是SpringBoot的一項宗旨,儘可能減小xml的配置。

在yml文件中的配置以下

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

接收這些配置信息的類以下

package com.example.FirstSpringBoot.Configuration;

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

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@ConfigurationProperties("acme")
public class AcmeProperties {

	private boolean enabled;

	private String remoteAddress;

	private final Security security = new Security();

	public boolean isEnabled() { return enabled; }

	public void setEnabled(boolean enabled) { this.enabled=enabled; }

	public String getRemoteAddress() { return remoteAddress; }

	public void setRemoteAddress(String remoteAddress) { this.remoteAddress=remoteAddress; }

	public Security getSecurity() { return security; }

	public static class Security {

		private String username;

		private String password;

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

		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; }

		public List<String> getRoles() { return roles; }

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

	}
}

而後再寫一個類將上面的類進行註冊進Spring中

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

而後在任何類中就能夠進行配置了

@Service
public class MyService {

    private final AcmeProperties acmeProperties;

    @Autowired
    public MyService(AcmeProperties acmeProperties){
        this.acmeProperties=acmeProperties;
    }

    @PostConstruct
    public void openConnection() {
        System.out.println("remote-address:"+acmeProperties.getRemoteAddress());
        System.out.println("username:"+acmeProperties.getSecurity().getUsername());
        System.out.println("role:"+acmeProperties.getSecurity().getRoles());
    }
}

這樣就能夠將配置文件中的屬性從bean中取出來,而不是一個一個@Value進行取了。其中@PostConstruct註解意思是在加載Servlet的時候進行運行,而且只運行一次。

2018-07-18 17:55:51.593  INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2018-07-18 17:55:51.599  INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-07-18 17:55:51.599  INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-07-18 17:55:51.599  INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-07-18 17:55:51.599  INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
remote-address:192.168.1.1
username:admin
role:[USER, ADMIN]

查看啓動信息就能夠知道,他是在加載Servlet的時候運行的。

8.1第三方的配置

若是你的配置想要做爲一個jar包供第三方進行使用,那麼能夠在與配置進行類型匹配的類中即上面提到的AcmeProperties類上面加上@Bean註解。這樣就能夠將配置進行打包傳輸了。

@ConfigurationProperties(prefix = "acme")
@Bean
public class AcmeProperties() {
	...
}

8.2對於資源文件的校驗

SpringBoiot提供了一套對資源文件的校驗。假如在資源文件中某個字段是不可或缺的,只要以下配置便可。

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

	@NotNull
	private String remoteAddress;

	// ... getters and setters

}

此時若是資源文件中沒有定義acme.remoteAddress的值的話那麼在項目啓動的時候就會報錯

Description:

Binding to target com.example.FirstSpringBoot.Configuration.AcmeProperties@2eadc9f6 failed:

    Property: acme.remoteAddress
    Value: null
    Reason: 不能爲null

當複雜的資源文件想要校驗怎麼辦?就以下配置便可

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

	@NotNull
	private String remoteAddress;

	@Valid
	private final Security security = new Security();

	// ... getters and setters

	public static class Security {

		@NotEmpty
		public String username;

		// ... getters and setters

	}

}

固然這個@Validated註解是SpringMvc中的註解,這裏就不詳細解釋了。關於@Validated的參考資料:

相關文章
相關標籤/搜索