不学无数——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的参考资料:

相关文章
相关标签/搜索