文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Boot 配置属性类型安全,你都了解了吗?

2024-12-01 19:00

关注

环境:Springboot2.4.12

准备环境

@Component
@ConfigurationProperties("pack")
public class PackProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public InetAddress getRemoteAddress() {
return remoteAddress;
}
public void setRemoteAddress(InetAddress 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;
}
@Override
public String toString() {
return "Security [username=" + username + ", password=" + password + ", roles=" + roles + ", " + roles.size()
+ "]";
}
}
@Override
public String toString() {
return "PackProperties [enabled=" + enabled + ", remoteAddress=" + remoteAddress + ", security=" + security + "]";
}
}

JavaBean属性绑定

绑定一个声明标准JavaBean属性的bean。

pack:
remote-address: 192.168.2.100
security:
roles: GUEST, ADMIN #List集合可用通过逗号`,`分割方式配置

输出:

PackProperties [enabled=false, remoteAddress=/192.168.2.100, security=Security [username=null, password=null, roles=[GUEST, ADMIN], 2]]

根据上面的JavaBean定义属性说明:

构造器绑定

修改上面的PackProperties。

@Component
@ConstructorBinding
@ConfigurationProperties("pack")
public class PackProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security;
public PackProperties(boolean enabled, InetAddress remoteAddress, Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
}

在此设置中,@ConstructorBinding注释用于指示应使用构造函数绑定。这意味着绑定器将期望找到一个包含您希望绑定的参数的构造函数。

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

可以使用@DefaultValue指定默认值,并且应用相同的转换服务将String值强制转换为缺失属性的目标类型。默认情况下,如果没有属性绑定到Security, PackProperties实例将包含用于security 的 null值。如果你希望返回一个非空的Security实例,即使没有属性绑定到它,你可以使用一个空的@DefaultValue注释来这样做:

如果只是上面那样配置,程序会报错,因为上面的PackProperties也是个Bean,并且只提供了一个有参数的构造函数,那么容器就会进行构造方法注入,从容器中查找参数类型的Bean进行注入,而容器当前是没有这些bean的,也就是说容器会吧构造函数中的参数以Bean的形式进行注入,并不会(也不知道)从配置文件中读取相关的值进行设置。通过如下方式可以实现构造函数的配置。

修改属性配置类。

@ConstructorBinding
@ConfigurationProperties("pack")
public class PackProperties {
}

在启动类上添加注解。

@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = {"com.pack"})
public class SpringWebDemoApplication {
}

该种方式就可以实现构造函数的注入。

该种方式也是在一个配置类或者启动类上添加注解。

@SpringBootApplication
@EnableConfigurationProperties(PackProperties.class)
public class SpringWebDemoApplication {
}

Enabling @ConfigurationProperties-annotated types

Spring Boot提供了基础设施来绑定@ConfigurationProperties类型并将它们注册为bean。可以逐个类地启用配置属性,也可以启用与组件扫描方式类似的配置属性扫描。

有时,带有@ConfigurationProperties注释的类可能不适合扫描,例如,如果你正在开发自己的自动配置,或者希望有条件地启用它们。在这些情况下,使用 @EnableConfigurationProperties注释指定要处理的类型列表。这可以在任何 @Configuration类上完成,如下所示:

@Configuration
@EnableConfigurationProperties(PackProperties.class)
public class PropConfig {
}

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

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

第三方配置

除了使用@ConfigurationProperties来注释类之外,还可以在公共的@Bean方法上使用它。当你希望将属性绑定到你无法控制的第三方组件时,这样做特别有用。

@ConfigurationProperties(prefix = "pack.third")
@Bean
public ThirdComponent thirdComponent() {
return new ThirdComponent();
}

在配置中配置的以pack.third为前缀的所有配置都将为JavaBean属性都被映射到ThirdComponent bean上。

@ConfigurationProperties验证

Spring Boot尝试验证@ConfigurationProperties类,只要它们被Spring的@Validated注解注解。您可以使用JSR-303 javax.validation约束注释直接在配置类上。要做到这一点,请确保类路径上有一个符合JSR-303的实现,然后向字段添加约束注释,如下所示:

@ConstructorBinding
@ConfigurationProperties("pack")
@Validated
public class PackProperties {
private boolean enabled;
@NotNull(message = "请输入远程地址")
private InetAddress remoteAddress;
}

注意:还需要确保环境中有JSR-303的实现,这里使用的Hidernate。

<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-validatorartifactId>
<version>6.0.7.Finalversion>
dependency>

如果没有配置remoteAddress,程序启动将会报错误。

Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'pack' to com.pack.propsbinding.PackProperties failed:
Property: pack.remoteAddress
Value: null
Reason: 请输入远程地址

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

@Component
@ConfigurationProperties("pack")
@Validated
public class PackProperties2 {
private boolean enabled;
@NotNull(message = "请输入远程地址")
private InetAddress remoteAddress;
@Valid
private Security security = new Security() ;
}

进过测试结果验证与官方文档不一致?嵌套属性即便不加@Valid注解也是可以在嵌套对象中的属性添加验证一样会生效。

@ConfigurationProperties vs. @Value

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

Feature

@ConfigurationProperties

@Value

宽松绑定

Yes

Limited (see note below)

元数据支持

Yes

No

SpEL表达式

No

Yes


来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯