当前位置: 首页 > 科技观察

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

时间:2023-03-13 08:20:33 科技观察

环境:Springboot2.4.12准备环境@Component@ConfigurationProperties("pack")publicclassPackProperties{私有InetAddress远程地址;privatefinalSecuritysecurity=newSecurity();publicbooleanisEnabled(){返回启用;}publicvoidsetEnabled(booleanenabled){this.enabled=enabled;}publicInetAddressgetRemoteAddress(){returnremoteAddress;}publicvoidsetRemoteAddress(InetAddressremoteAddress){this.remoteAddress=remoteAddress;}publicSecuritygetSecurity(){返回安全;}publicstaticclassSecurity{私有字符串用户名;私有字符串密码;privateListroles=newArrayList<>(Collections.singleton("USER"));publicStringgetUsername(){返回用户名;}publicvoidsetUsername(Stringusername){this.username=username;}publicStringgetPassword(){返回密码}publicvoidsetPassword(Stringpassword){this.password=password;}publicListgetRoles(){返回角色;}publicvoidsetRoles(Listroles){this.roles=roles;}@OverridepublicStringtoString(){return"Security[username="+username+",password="+password+",roles="+roles+","+roles.尺寸()+“]”;}}@OverridepublicStringtoString(){return"PackProperties[enabled="+enabled+",remoteAddress="+remoteAddress+",security="+security+"]";}}JavaBean属性绑定绑定一个声明的标准JavaBean属性beanpack:remote-address:192.168.2.100security:roles:GUEST,ADMIN#List集合可以用逗号`,`分隔来配置输出:PackProperties[enabled=false,remoteAddress=/192.168.2.100,security=Security[username=null,password=null,roles=[GUEST,ADMIN],2]]根据上面的JavaBean定义属性说明:pack.enabled,默认为false。pack.remote-address,自动从String转换为InetAddress。pack.security.username,使用嵌套的“security”对象,其名称由属性名称决定。特别是,这里根本不使用返回类型,可以使用SecurityProperties。pack.security.roles,使用默认为USER的String集合。构造函数绑定修改上面的PackProperties。@Component@ConstructorBinding@ConfigurationProperties("pack")publicclassPackProperties{privatebooleanenabled;私有InetAddress远程地址;私人最终安全保障;publicPackProperties(booleanenabled,InetAddressremoteAddress,Security.=remoteAddress;this.security=security;}}在此设置中,@ConstructorBinding注释用于指示应使用构造函数绑定。这意味着活页夹将期望找到包含您希望绑定的参数的构造函数。@ConstructorBinding类的嵌套成员(如上例中的Security)也将通过它们的构造函数进行绑定。可以使用@DefaultValue指定默认值,并应用相同的转换服务将字符串值强制转换为缺失属性的目标类型。默认情况下,如果没有属性绑定到安全性,PackProperties实例将包含安全性的空值。如果你想返回一个非空的Security实例,即使它没有绑定任何属性,你也可以使用一个空的@DefaultValue注解来实现:如果你只是像上面那样配置,程序会报错,因为上面的PackProperties也是一个Bean,并且只提供了一个带参数的构造函数,那么容器会进行构造函数注入,从容器中找到该参数类型的bean进行注入,而容器当前没有这些bean,即比如说,容器会使用以Beans形式注入的参数,并不会(也不知道)从配置文件中读取相关值进行设置。构造函数的配置可以通过以下方式实现。@ConfigurationPropertiesScan.修改属性配置类。@ConstructorBinding@ConfigurationProperties("pack")publicclassPackProperties{}为启动类添加注解。@SpringBootApplication@ConfigurationPropertiesScan(basePackages={"com.pack"})publicclassSpringWebDemoApplication{}这个方法可以实现构造函数注入。@EnableConfigurationProperties。此方法还向配置类或启动类添加注释。@SpringBootApplication@EnableConfigurationProperties(PackProperties.class)publicclassSpringWebDemoApplication{}启用@ConfigurationProperties注释类型SpringBoot提供了绑定@ConfigurationProperties类型并将它们注册为bean的基础设施。可以逐个类地启用配置属性,或者以类似于组件扫描的方式扫描配置属性。有时使用@ConfigurationProperties注释的类可能不适合扫描,例如,如果您正在开发自己的自动配置或想要有条件地启用它们。在这些情况下,使用@EnableConfigurationProperties注释来指定要处理的类型列表。这可以在任何@Configuration类上完成,如下所示:@Configuration@EnableConfigurationProperties(PackProperties.class)publicclassPropConfig{}要使用配置属性扫描,请将@ConfigurationPropertiesScan注释添加到您的应用程序。通常,它被添加到用@SpringBootApplication注释的主应用程序类中,但它也可以添加到任何@Configuration类中。默认情况下,将从声明注释类的包中进行扫描。如果你想定义特定的包来扫描,你可以这样做,如下例所示:@SpringBootApplication@ConfigurationPropertiesScan({"com.pack.app","org.pack.another"})publicclassMyApplication{}Section除了使用@ConfigurationProperties来注解类之外,三路配置也可以用在公共的@Bean方法上。当您想要将属性绑定到不受您控制的第三方组件时,这尤其有用。@ConfigurationProperties(prefix="pack.third")@BeanpublicThirdComponentthirdComponent(){returnnewThirdComponent();}以pack.third为前缀的配置中配置的所有配置都会被映射到ThirdComponentbean的JavaBean属性。@ConfigurationProperties验证SpringBoot会尝试验证@ConfigurationProperties类,只要它们使用Spring的@Validated注释进行注释。您可以直接在配置类上使用JSR-303javax.validation约束注释。为此,请确保您的类路径上有符合JSR-303的实现,然后向字段添加约束注释,如下所示:@ConstructorBinding@ConfigurationProperties("pack")@ValidatedpublicclassPackProperties{privatebooleanenabled;@NotNull(message="Pleaseentertheremoteaddress")privateInetAddressremoteAddress;}注意:还需要保证环境中有JSR-303的实现,这里使用了Hidernate。org.hibernatehibernate-validator6.0.7.Final如果没有配置remoteAddress会报错当程序启动时。绑定到目标org.springframework.boot.context.properties.bind.BindException:无法将“pack”下的属性绑定到com.pack.propsbinding.PackProperties失败:属性:pack.remoteAddress值:null原因:请输入远程地址为了确保对嵌套属性始终触发验证,即使没有找到属性,关联的字段也必须使用@Valid注解。以下示例建立在前面的PackProperties示例之上:@Component@ConfigurationProperties("pack")@ValidatedpublicclassPackProperties2{privatebooleanenabled;@NotNull(message="请输入远程地址")privateInetAddressremoteAddress;@ValidprivateSecuritysecurity=newSecurity();}测试结果验证与官方文档不一致?即使嵌套属性没有使用@Valid注解,也可以通过在嵌套对象中为属性添加验证来生效。@ConfigurationProperties与@Value@Value注释是一个核心容器特性,它不提供与类型安全配置属性相同的特性。下表总结了@ConfigurationProperties和@Value支持的特性:Feature@ConfigurationProperties@ValueloosebindingYesLimited(seenotebelow)metadatasupportsYesNoSpELexpressionNoYes