【Spring Boot 初识丨九丨 外部化配置(三)】类型安全配置属性

2023-11-08

上一篇讲了 Spring Boot 的外部化配置的加载顺序及一些简单的属性说明
本篇来讲一讲 外部化配置类型安全属性
Spring Boot 初识:
【Spring Boot 初识丨一】入门实战
【Spring Boot 初识丨二】maven
【Spring Boot 初识丨三】starter
【Spring Boot 初识丨四】主应用类
【Spring Boot 初识丨五】beans
【Spring Boot 初识丨六】依赖注入
【Spring Boot 初识丨七 丨 外部化配置(一)】属性详解
【Spring Boot 初识丨八 丨 外部化配置(二)】外部应用程序属性

在这里插入图片描述

类型安全配置属性


  使用@Value(“${property}”)注释来注入配置属性有时可能很麻烦,尤其是处理多个属性或您的数据本质上是层次结构的情况下。Spring Boot 提供了另一种使用属性的方法,让强类型 bean 管理和验证应用程序的配置。

JavaBean 属性绑定


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

    }

}


POJO 定义了以下属性:

  • my.service.enabled,默认值为false。
  • my.service.remote-address,具有可以从 强制的类型String。
  • my.service.security.username,带有一个嵌套的“安全”对象,其名称由属性名称确定。特别是,该类型根本没有在那里使用,并且本来可以使用SecurityProperties。
  • my.service.security.password。
  • my.service.security.roles,其中的集合String默认为USER。

注意:
  映射到 Spring Boot 中可用的@ConfigurationProperties类的属性(通过属性文件、YAML 文件、环境变量和其他机制进行配置)是公共API,但类本身的访问器(getter/setter)并不意味着可以直接使用。

你需要使用 @EnableConfigurationProperties 注解将属性类注入配置类中。

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

注意:
  这种安排依赖于默认的空构造函数,并且 getter 和 setter 通常是强制性的,因为绑定是通过标准 Java Beans 属性描述符进行的,就像在 Spring MVC中一样。在以下情况下可以省略 setter:

  • 映射,只要它们被初始化,就需要一个 getter,但不一定需要一个 setter,因为它们可以被绑定器改变。
  • m可以通过索引(通常使用 YAML)或使用单个逗号分隔值(属性)来访问集合和数组。在后一种情况下,setter 是强制性的。我们建议始终为此类类型添加 setter。如果初始化集合,请确保它不是不可变的(如前面的示例所示)。
  • 如果嵌套 POJO 属性已初始化(如前面示例中的Security字段),则不需要 setter。如果您希望绑定器使用默认构造函数动态创建实例,则需要一个setter。

  有些人使用 Project Lombok 自动添加 getter 和 setter。确保 Lombok不会为此类类型生成任何特定的构造函数,因为容器会自动使用它来实例化对象。

  最后,仅考虑标准 Java Bean 属性,并且不支持静态属性的绑定。

构造函数绑定


上一节中的示例可以以不可变的方式重写,示例如下:

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

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

@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注释来指定用于构造函数绑定的构造函数。要选择退出具有单个参数化构造函数的类的构造函数绑定,该构造函数必须使用@Autowired 进行注释。

  构造函数绑定可以与记录一起使用。除非您的记录有多个构造函数,否则无需使用@ConstructorBinding。

  构造函数绑定类的嵌套成员(例如上面的示例Security)也将通过其构造函数进行绑定。

  可以使用@DefaultValue 在构造函数参数和记录组件指定默认值。转换服务将用于将注释的String值强制转换为缺失属性的目标类型。

  参考前面的示例,如果没有属性绑定到Security,则MyProperties实例将包含null的值。要使其包含非空security实例,即使没有绑定任何属性(使用 Kotlin 时,这将要求Security 的username和password参数声明为可为空,因为它们没有默认值),请使用空的@DefaultValue注释:

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

注意:
  要使用构造函数绑定,必须使用@EnableConfigurationProperties或配置属性扫描来启用类。您不能将构造函数绑定到由常规Spring 机制创建的 bean(例如@Componentbean、使用@Bean方法创建的 bean 或使用 @Import加载的bean )。
   要在本机映像中使用构造函数绑定,必须使用-parameters编译类。 如果您使用 Spring Boot 的Gradle 插件或者使用 Maven 和spring-boot-starter-parent,将会自动编译。
  在java,util 中不建议使用@ConfigurationProperties,因为它主要用作返回类型。因此,它不太适合配置属性注入。为了与其他类型的属性保持一致,如果声明了一个Optional属性并且它没有值,则将绑定null,而不是空的Optional。

松散的绑定规则

  Spring Boot 使用一些宽松的规则将Environment属性绑定到bean,因此属性名称和 bean 属性名称@ConfigurationProperties之间不需要完全匹配。Environment此功能有用的常见示例包括用破折号分隔的环境属性(例如,context-path绑定到contextPath)和大写的环境属性(例如,PORT绑定到port)。
示例如下:

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

}

松散的绑定:

Property Note
my.main-project.person.first-name 建议使用在.properties 和 YAML 文件。- 分隔
my.main-project.person.firstName 标准的驼峰大小写语法。
my.main-project.person.first_name 下划线_ 在.properties 和 YAML 文件 使用的另一种格式
my.main-project.person.first_name 大写格式, 推荐在使用环境系统变量时使用。

每个属性源的松散绑定规则:

Property Source Simple List
Properties Files 驼峰式大小写、烤肉串大小写或下划线表示法 使用[ ] 或 逗号分隔值的标准列表语法
YAML Files 驼峰式大小写、烤肉串大小写或下划线表示法 标准 YAML 列表语法或逗号分隔值
Environment Variables 大写格式,下划线作为分隔符 用下划线包围的数值
System properties 驼峰式大小写、烤肉串大小写或下划线表示法 使用[ ] 或 逗号 分隔值的标准列表语法

属性转换


  Spring Boot 在绑定到@ConfigurationPropertiesbean 时尝试将外部应用程序属性强制转换为正确的类型。

  如果需要类型转换,你可以提供一个 ConversionService bean (一个名叫 conversionService 的 bean) 或自定义属性配置 (一个 CustomEditorConfigurer bean) 或自定义的 Converters (带有@ConfigurationPropertiesBinding 注解修饰的 bean)。

注:
由于此 bean 在应用程序生命周期的早期就被请求,因此请确保限制您ConversionService正在使用的依赖项。通常,您需要的任何依赖项在创建时可能不会完全初始化。如果配置键强制不需要ConversionService ,并且仅依赖于使用@ConfigurationPropertiesBinding限定的自定义转换器,您可能需要重命名您的自定义ConversionService 。

在这里插入图片描述

  如果喜欢的话,欢迎 									
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Spring Boot 初识丨九丨 外部化配置(三)】类型安全配置属性 的相关文章

  • java.lang.NoClassDefFoundError:org.apache.batik.dom.svg.SVGDOMImplementation

    我在链接到我的 Android LibGDX 项目的 Apache Batik 库时遇到了奇怪的问题 但让我们从头开始 在 IntelliJ Idea 中我有一个项目 其中包含三个模块 Main Android 和 Desktop 我强调的
  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 我可以使用 HSQLDB 进行 junit 测试克隆 mySQL 数据库吗

    我正在开发一个 spring webflow 项目 我想我可以使用 HSQLDB 而不是 mysql 进行 junit 测试吗 如何将我的 mysql 数据库克隆到 HSQLDB 如果您使用 spring 3 1 或更高版本 您可以使用 s
  • Spring @RequestMapping 带有可选参数

    我的控制器在请求映射中存在可选参数的问题 请查看下面的控制器 GetMapping produces MediaType APPLICATION JSON VALUE public ResponseEntity
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何从泛型类调用静态方法?

    我有一个包含静态创建方法的类 public class TestClass public static
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐

  • elementui-slider 滑动时会重置为0的问题解决

    文章目录 问题描述 问题排查 问题解决 总结 问题描述 首次打开有 elementui slider的页面 不管滑动哪个滑块 滑动时都会自动归0 划得动 但是会自动回到最左侧0的位置 但是他确实触发了change函数 问题排查 尝试了很多方
  • Sentinel限流算法详解(硬啃)

    文章目录 常见四种限流算法 固定窗口计数器 滑动窗口计数器 漏桶 也有称漏斗 Leaky bucket 令牌桶 Token bucket Sentinel源码举例 滑动窗口 漏桶 令牌桶 常见四种限流算法 固定窗口计数器 固定窗口 相比其他
  • 如何进入安全模式? windows系统使用小技巧

    一 Windows95环境下进入安全模式 1 开启计算机 如果正在运行Windows 请重启计算机 2 在计算机开启时 请留意观察屏幕 当出现Starting Windows 95的时候 按住F5键 这样就能进入安全模式 3 或者 在计算机
  • easyexcel poi 一个模板导出excel包含多个sheet

    easy poi 一个模板导出excel包含多个sheet 1 简述 2 导出代码实例 3 导出模板 4 导出效果 5 项目实战案例 1 简述 通过调用ExcelExportUtil exportExcelClone map params
  • mybatis原理(含图)

    上面中流程就是MyBatis内部核心流程 每一步流程的详细说明如下文所述 1 读取MyBatis的配置文件 mybatis config xml为MyBatis的全局配置文件 用于配置数据库连接信息 2 加载映射文件 映射文件即SQL映射文
  • 字符的点阵显示(模拟户外广告显示屏)

    字符的点阵显示 电子科技大学软件学03级02班 周银辉一 效果二 关于C 读取字符点阵的代码 原理就不再阐述了 到Baidu里面搜一下 很多 不过一般都是C C 的 说明 对于一个字符 GetWordLattics函数返回的bool 表示一
  • Windows 10

    前言 Windows作为工作机 对于计算机系的同学来说 主要是在于利用图形化的界面直观的创建虚拟机 典型的有代表性的是virtualbox和VMware这两家公司的桌面级虚拟化软件 尤其是小白这样的初学者 更高层次的虚拟机技术才是kvm x
  • 信息安全技术 网络安全漏洞分类分级指南

    声明 本文是学习GB T 30279 2020 信息安全技术 网络安全漏洞分类分级指南 而整理的学习笔记 分享出来希望更多人受益 如果存在侵权请及时联系我们 网络安全漏洞分级 概述 网络安全漏洞分级根据漏洞分级的场景不同 分为技术分级和综合
  • 这里是哪里错显示[Error] ‘else‘ without a previous ‘if‘?

    include
  • (c语言 )输入10个学生5门课的成绩,分别用函数求:每个学生平均分;每门课的平均分;

    c语言 输入10个学生5门课的成绩 分别用函数求 每个学生平均分 每门课的平均分 include
  • 新版Spring Boot(9)- Spring Boot 整合 Web 开发(5)

    1 路径映射 不需要每个Controller都加路径映射 Configuration public class WebMvcConfig implements WebMvcConfigurer 页面只是简单的返回 不需要返回数据 param
  • WPF Image 旋转图片方法

    WPF在对图片进行旋转时 可以使用Image RenderTransform 设置它的初始旋转角度Angle 默认是0 在旋转照片图像时 还需要设置图片的旋转中心 CenterX CenterY 一般都设置它的宽度一半 高度一半 先看一下效
  • php按钮添加post请求,PHP发送POST请求的常用方式

    PHP发送POST请求我们使用的是curl来操作了 下面来看看一些常用的post数据的例子 具体的一起和111cn小编来看看吧 在PHP开发的过程中经常需要发送POST请求 POST相比GET要安全很多 而且传输的数据量也较大 下面PHP程
  • uboot启动内核的相关命令详解——boot、bootm

    1 boot和bootm命令的联系 当我们进入uboot的命令终端后 可以利用boot和bootm来启动内核 但是命令的使用方式有区别 直接输入boot命令就可以启动内核 如果使用bootm命令 后面还需要传入内核在DDR中的地址 1 bo
  • css内容达到最底部但滚动条没有滚动到底部

    也是犯了一个傻狗一样的错误 滚动条样式是直接复制的蓝湖的代码 有个高度 然后就出现了这样的bug 看了好久一直以为是布局或者overflow的问题 最后发现是因为我给这个滚动条加了个高度 我也是傻狗一样的 滚动条高度是通过内容计算出来的 怎
  • QTabWidget 竖向 QTabBar横向

    参考文件引用自http blog csdn net skyztttt article details 52448992 你的评论 是我的动力 正常设置QTabWidget gt setTabPosition QTabWidget West
  • 2023年第一届山东省职业技能大赛“网络安全”赛项B模块任务书

    2023年第一届山东省职业技能大赛 网络安全 赛项B模块任务书 模块B 网络安全事件响应 数字取证调查和应用程序安全 1竞赛项目简介 1 1 介绍 1 2 所需的设备 机械 装置和材料 1 3 评分方案 1 4 项目和任务的描述 2工作任务
  • React-JSX

    react JSX 这种在js里面写标签的语法叫JSX 所谓的JSX其实就是JS的对象 JSX就是Javascript和XML结合的一种格式 React发明了JSX 利用HTML语法来创建虚拟DOM 当遇到 lt JSX就当HTML解析 遇
  • 如何以管理员的身份唤起powershell

    使用运行窗口打开带管理员权限的PowerShell 1 按下组合键Windows R以打开运行窗口 输入powershell然后按下回车键 2 Windows PowerShell会以当前用户的权限去执行 3 如果你想要从普通模式转至管理员
  • 【Spring Boot 初识丨九丨 外部化配置(三)】类型安全配置属性

    上一篇讲了 Spring Boot 的外部化配置的加载顺序及一些简单的属性说明 本篇来讲一讲 外部化配置类型安全属性 Spring Boot 初识 Spring Boot 初识丨一 入门实战 Spring Boot 初识丨二 maven S
Powered by Hwhale