springCore完整学习教程2,入门级别-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

上集说到2. 3咱们从2.3集开始

2. Externalized Configuration

2.3. External Application Properties
Spring Boot会自动找到并加载应用程序。属性和应用程序。当应用程序启动时从以下位置获取Yaml文件:

从类路径

类路径root

类路径/配置包

从当前目录

 使用当前目录

当前目录下的config/子目录

config/子目录的直接子目录

该列表按优先级排序(较低项的值覆盖较早项的值)。加载文件中的文档作为propertresources添加到Spring环境中。
如果您不喜欢application作为配置文件名您可以通过指定spring.config.name环境属性来切换到另一个文件名。例如查找我的项目。属性和myproject。你可以这样运行你的应用程序:

2.3.1. Optional Locations

默认情况下当指定的配置数据位置不存在时Spring Boot将抛出ConfigDataLocationNotFoundException并且您的应用程序将不会启动。

如果您想指定一个位置但不介意它不总是存在则可以使用可选的:前缀。您可以将此前缀与spring.config.location和spring.config一起使用。附加位置属性以及spring.config.import声明。
例如spring.config.import的值为optional:file:./myconfig。属性允许您的应用程序启动即使myconfig。属性文件丢失。

如果你想忽略所有的configdatalocationnotfoundexception并始终继续启动你的应用程序你可以使用spring.config。on-not-found财产。使用SpringApplication.setDefaultProperties(…)或使用系统/环境变量将值设置为忽略。

2.3.2. Wildcard Locations

使用通配符

例如如果你有一些Redis配置和一些MySQL配置你可能希望将这两部分配置分开同时要求这两部分都存在于应用程序中。属性文件。这可能导致两个独立的应用程序。属性文件挂载在不同的位置如/config/redis/application。Properties和/config/mysql/application.properties。在这种情况下使用通配符位置config/*/将导致两个文件都被处理。

默认情况下Spring Boot在默认搜索位置中包含config/*/。这意味着将搜索jar之外的/config目录的所有子目录。

通配符位置必须只包含一个*并以*/结尾如果搜索位置是目录或者如果搜索位置是文件则必须包含*/<filename>。带有通配符的位置根据文件名的绝对路径按字母顺序排序。

通配符位置仅适用于外部目录。不能在类路径:location中使用通配符。

2.3.3. Profile Specific Files

就是application-{profile}.yml等  的类型

特定于配置文件的属性是从与标准应用程序相同的位置加载的。属性特定于配置文件的文件总是覆盖非特定的文件。如果指定了多个配置文件则应用最后获胜策略。例如如果profile prod、live是由spring.profiles.active属性指定的那么application-prod中的值就会被替换。属性可以被application-live.properties中的属性覆盖。

spring.profiles.active=prod
2.3.4. Importing Additional Data

应用程序属性可以使用spring.config.import属性从其他位置导入配置数据。当发现导入时将对其进行处理并将其视为插入声明导入的文档下面的附加文档。

例如在您的类路径应用程序中可能有以下内容。属性文件:

spring.application.name=myapp
spring.config.import=optional:file:./dev.properties

这将触发在当前目录中导入dev.properties文件(如果存在这样的文件)。导入的dev.properties中的值将优先于触发导入的文件。在上面的例子中dev.properties可以将spring.application.name重新定义为一个不同的值。

这里我举个例子吧

application-prod.yml文件

server:
  port: 3344
spring:
  config:
    import: classpath:/config/dev.properties
  application:
    name: myapp

dev.properties

spring.applicdation.name=bb
package com.example.demo.demos;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Test {

    @Value("${spring.application.name}")
    public String name;
    @GetMapping("/get")
    public String getName(){
        return name;
    }

}

访问localhost:3344/get

发现生成的是

这个例子很明显吧明显还不关注我

2.3.5. Importing Extensionless Files

某些云平台无法为卷挂载的文件添加文件扩展名。要导入这些无扩展文件需要给Spring Boot一个提示以便它知道如何加载它们。您可以通过在方括号中添加扩展提示来实现这一点。

比如

spring.config.import=file:/etc/config/myconfig[.yaml]
2.3.6. Using Configuration Trees

在云平台(如Kubernetes)上运行应用程序时通常需要读取平台提供的配置值。出于这种目的使用环境变量并不罕见但这可能有缺点特别是在值应该保密的情况下。

2.3.7. Property Placeholders

应用中的值。属性和应用程序。yaml在使用时将通过现有环境进行过滤因此您可以引用以前定义的值(例如从系统属性或环境变量)。标准的${name}属性占位符语法可以在值中的任何地方使用。属性占位符还可以使用:指定默认值以将默认值与属性名称分开例如${name:default}。
以下示例显示了带默认值和不带默认值的占位符的使用:

app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}

假如用户名属性没有在其他地方设置app.description将具有MyApp是由Unknown编写的Spring Boot应用程序的值。

2.3.8. Working With Multi-Document Files

Spring Boot允许您将单个物理文件拆分为多个逻辑文档每个文档都是独立添加的。文档按照从上到下的顺序进行处理。以后的文档可以覆盖以前文档中定义的属性。
为应用程序。yaml文件则使用标准的yaml多文档语法。三个连续的连字符表示一个文档的结束和下一个文档的开始。
例如下面的文件有两个逻辑文档:

spring:
  application:
    name: "MyApp"
---
spring:
  application:
    name: "MyCloudApp"
  config:
    activate:
      on-cloud-platform: "kubernetes"

like this

spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes

两个物理文件但是有三个逻辑项目

2.3.9. Activation Properties

有时只有在满足某些条件时才激活给定的一组属性是有用的。例如您可能拥有仅在特定概要文件处于活动状态时才相关的属性。
您可以使用spring.config.activate.*有条件地激活属性文档。
以下激活属性可用:

PropertyNote

on-profile

A profile expression that must match for the document to be active.

on-cloud-platform

The CloudPlatform that must be detected for the document to be active.

例如下面的命令指定第二个文档仅在Kubernetes上运行时才激活并且仅当“prod”或“staging”配置文件处于激活状态时才激活:

myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-set

2.4. Encrypting Properties

Spring Boot没有为加密属性值提供任何内置支持但是它提供了修改Spring环境中包含的值所必需的钩子点。

2.5. Working With YAML

YAML是JSON的超集因此是指定分层配置数据的方便格式。只要在你的类路径上有SnakeYAML库SpringApplication类就会自动支持YAML作为属性的替代。

2.5.1. Mapping YAML to Properties

YAML文档需要从层次结构格式转换为可与Spring环境一起使用的平面结构。例如考虑以下YAML文档:

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

为了从环境中访问这些属性它们将被扁平化如下:

environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App
2.5.2. Directly Loading YAML

Spring Framework提供了两个方便的类可用于加载YAML文档。YamlPropertiesFactoryBean将YAML作为属性加载而YamlMapFactoryBean将YAML作为Map加载。
你也可以使用YamlPropertySourceLoader类如果你想加载YAML作为一个Spring PropertySource。

2.6. Configuring Random Values

RandomValuePropertySource对于注入随机值很有用(例如在秘密或测试用例中)。它可以生成整数、长整数、uuid或字符串示例如下:

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

我都测试过了各位当真不点关注0.0

2.7. Configuring System Environment Properties

Spring Boot支持为环境属性设置前缀。如果系统环境由具有不同配置需求的多个Spring Boot应用程序共享这将非常有用。系统环境属性的前缀可以直接在SpringApplication上设置。
例如如果将前缀设置为input则远程。超时也将在系统环境中解析为input.remote.timeout。

2.8. Type-safe Configuration Properties

使用@Value("${property}")注释注入配置属性有时会很麻烦特别是在处理多个属性或数据本质上是分层的情况下。Spring Boot提供了另一种处理属性的方法让强类型bean管理和验证应用程序的配置。

2.8.1. JavaBean Properties Binding

可以绑定声明标准JavaBean属性的bean如下例所示:

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

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

@ConfigurationProperties("my.service")
public class MyProperties {

    private boolean enabled;

    private InetAddress remoteAddress;

    private final Security security = new Security();

    public boolean isEnabled() {
        return this.enabled;
    }

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

    public InetAddress getRemoteAddress() {
        return this.remoteAddress;
    }

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

    public Security getSecurity() {
        return this.security;
    }

    public static class Security {

        private String username;

        private String password;

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

        public String getUsername() {
            return this.username;
        }

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

        public String getPassword() {
            return this.password;
        }

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

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

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

    }

}

  • my.service.enabled, with a value of false by default.

  • my.service.remote-address, with a type that can be coerced from String.

  • my.service.security.username, with a nested "security" object whose name is determined by the name of the property. In particular, the type is not used at all there and could have been SecurityProperties.

  • my.service.security.password.

  • my.service.security.roles, with a collection of String that defaults to USER.

配置一下主类

@ConfigurationPropertiesScan(basePackages = "com.example.demo.demos")

在配置文件上写

my.service.enabled=true
my.service.remoteAddress=127.0.0.1
my.service.security.username=admin
my.service.security.password=admin123
my.service.security.roles=USER,ADMIN

就可以测试了自己测试吧又不关注我凭什么给你们测试哼

2.8.2. Constructor Binding

上一节的例子可以用不可变的方式重写如下面的例子所示:

import java.net.InetAddress;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;

@ConstructorBinding
@ConfigurationProperties("my.service")
public class MyProperties {

    private final boolean enabled;

    private final InetAddress remoteAddress;

    private final Security security;

    public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
        this.enabled = enabled;
        this.remoteAddress = remoteAddress;
        this.security = security;
    }

    public boolean isEnabled() {
        return this.enabled;
    }

    public InetAddress getRemoteAddress() {
        return this.remoteAddress;
    }

    public Security getSecurity() {
        return this.security;
    }

    public static class Security {

        private final String username;

        private final String password;

        private final List<String> roles;

        public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
            this.username = username;
            this.password = password;
            this.roles = roles;
        }

        public String getUsername() {
            return this.username;
        }

        public String getPassword() {
            return this.password;
        }

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

    }

}

在这个设置中@ConstructorBinding注释用于指示应该使用构造函数绑定。这意味着绑定器将期望找到一个构造函数其中包含您希望绑定的参数。如果使用的是Java 16或更高版本则可以对记录使用构造函数绑定。在这种情况下除非您的记录有多个构造函数否则不需要使用@ConstructorBinding。
@ConstructorBinding类的嵌套成员(如上面示例中的Security)也将通过它们的构造函数绑定。
默认值可以使用@DefaultValue on来指定

2.8.3. Enabling @ConfigurationProperties-annotated Types

Spring Boot提供了绑定@ConfigurationProperties类型并将它们注册为bean的基础设施。您既可以逐个类地启用配置属性也可以启用与组件扫描类似的配置属性扫描。
有时带有@ConfigurationProperties注释的类可能不适合扫描例如如果您正在开发自己的自动配置或者希望有条件地启用它们。在这些情况下使用@ enablecconfigurationproperties注释指定要处理的类型列表。

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {

}

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

@ConfigurationProperties("some.properties")
public class SomeProperties {

}

要使用配置属性扫描请在应用程序中添加@ConfigurationPropertiesScan注释。通常它被添加到带有@SpringBootApplication注释的主应用程序类中但它也可以添加到任何@Configuration类中。默认情况下将从声明注释的类的包进行扫描。如果您想定义要扫描的特定包可以这样做如下所示:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {

}

2.8.6. Relaxed Binding

Spring Boot使用一些宽松的规则将Environment属性绑定到@ConfigurationProperties bean因此在Environment属性名和bean属性名之间不需要精确匹配。这很有用的常见示例包括用虚线分隔的环境属性(例如上下文路径绑定到contextPath)和大写的环境属性(例如PORT绑定到PORT)。

例如考虑下面的@ConfigurationProperties类:

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

@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {

    private String firstName;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

}

使用上述代码可以使用以下属性名称:

PropertyNote

my.main-project.person.first-name

Kebab case, which is recommended for use in .properties and YAML files.

my.main-project.person.firstName

Standard camel case syntax.

my.main-project.person.first_name

Underscore notation, which is an alternative format for use in .properties and YAML files.

MY_MAINPROJECT_PERSON_FIRSTNAME

Upper case format, which is recommended when using system environment variables.

注释的前缀值必须是kebab case(小写并用-分隔如my.main-project.person)上面使用了驼峰命名法。

2.8.7. Merging Complex Types

当列表在多个位置配置时重写通过替换整个列表来工作。
例如假设MyPojo对象的名称和描述属性默认为空。下面的例子展示了MyProperties中的MyPojo对象列表:

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

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

@ConfigurationProperties("my")
public class MyProperties {

    private final List<MyPojo> list = new ArrayList<>();

    public List<MyPojo> getList() {
        return this.list;
    }

}

考虑以下配置:

my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
2.8.8. Properties Conversion

当Spring Boot绑定到@ConfigurationProperties bean时它尝试将外部应用程序属性强制为正确的类型。如果您需要自定义类型转换您可以提供ConversionService bean(带有名为ConversionService的bean)或自定义属性编辑器(通过CustomEditorConfigurer bean)或自定义转换器(带有注释为@ConfigurationPropertiesBinding的bean定义)。

2.8.9. @ConfigurationProperties Validation

每当@ConfigurationProperties类被Spring的@Validated注释时Spring Boot都会尝试验证它们。您可以使用JSR-303 javax。直接在配置类上验证约束注释。要做到这一点请确保在你的类路径上有一个兼容的JSR-303实现然后向你的字段添加约束注释如下例所示:

import java.net.InetAddress;

import javax.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

    @NotNull
    private InetAddress remoteAddress;

    public InetAddress getRemoteAddress() {
        return this.remoteAddress;
    }

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

}

您还可以通过用@Validated注释创建配置属性的@Bean方法来触发验证。

为了确保总是触发对嵌套属性的验证即使没有找到任何属性也必须用@Valid注释关联字段。下面的示例建立在前面的MyProperties示例之上:

import java.net.InetAddress;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

    @NotNull
    private InetAddress remoteAddress;

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

    public InetAddress getRemoteAddress() {
        return this.remoteAddress;
    }

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

    public Security getSecurity() {
        return this.security;
    }

    public static class Security {

        @NotEmpty
        private String username;

        public String getUsername() {
            return this.username;
        }

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

    }

}

您还可以通过创建一个名为configurationPropertiesValidator的bean定义来添加自定义Spring Validator。@Bean方法应该声明为静态的。配置属性验证器是在应用程序生命周期的早期创建的并且将@Bean方法声明为静态可以在不实例化@Configuration类的情况下创建bean。这样做可以避免可能由早期实例化引起的任何问题。

2.8.10. @ConfigurationProperties vs. @Value

@Value注释是容器的核心特性它不提供与类型安全配置属性相同的特性。下表总结了@ConfigurationProperties和@Value支持的特性:

Feature@ConfigurationProperties@Value

Relaxed binding

Yes

Limited (see note below)

Meta-data support

Yes

No

SpEL evaluation

No

Yes

如果您确实想使用@Value我们建议您使用规范形式(仅使用小写字母的kebab-case)引用属性名。这将允许Spring Boot使用与放松绑定@ConfigurationProperties时相同的逻辑。
例如@Value("${demo.item-price}")将选择demo。项目价格和演示。itemPrice表单。属性文件以及系统环境中的DEMO_ITEMPRICE。如果你使用了@Value("${demo. itemprice}") demo. itemprice将会被替换。item-price和DEMO_ITEMPRICE将不被考虑。

如果您为自己的组件定义了一组配置键我们建议您将它们分组在带有@ConfigurationProperties注解的POJO中。这样做将为您提供结构化的、类型安全的对象您可以将其注入到自己的bean中。
在解析这些文件和填充环境时不会处理来自应用程序属性文件的SpEL表达式。但是可以在@Value中编写斯佩尔表达式。如果应用程序属性文件中的属性值是一个SpEL表达式则在通过@Value使用时对其进行计算。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring