微信公众号:一个优秀的废人。如有问题,请后台留言,反正我也不会听。前言
最近有跳槽的想法,所以故意复习了下 SpringBoot 的相关知识,复习得比较细。其中有些,我感觉是以前忽略掉的东西,比如 @Value 和 @ConfigurationProperties 的区别 。
如何使用定义两个对象,一个学生对象,对应着一个老师对象,代码如下:
@ConfigurationProperties
学生类
@Component @ConfigurationProperties(prefix = "student") // 指定配置文件中的 student 属性与这个 bean绑定 public class Student { private String firstName; private String lastName; private Integer age; private String gender; private String city; private Teacher teacher; private Listhobbys; private Map scores; //注意,为了测试必须重写 toString 和 get,set 方法 }
老师类
public class Teacher { private String name; private Integer age; private String gender; //注意,为了测试必须重写 toString 和 get,set 方法 }
测试类
@RunWith(SpringRunner.class) @SpringBootTest public class SpringbootValConproDemoApplicationTests { @Autowired private Student student; @Test public void contextLoads() { // 这里为了方便,但工作中千万不能用 System.out System.out.println(student.toString()); } }
输出结果
Student{firstName="陈", lastName="一个优秀的废人", age=24, gender="男", city="广州", teacher=Teacher{name="eses", age=24, gender="女"}, hobbys=[篮球, 羽毛球, 兵兵球], scores={java=100, Python=99, C=99}}
@Value
@Value 支持三种取值方式,分别是 字面量、${key}从环境变量、配置文件中获取值以及 #{SpEL}
学生类
@Component //@ConfigurationProperties(prefix = "student") // 指定配置文件中的 student 属性与这个 bean绑定 public class Student { /** ** * */ @Value("陈") // 字面量 private String firstName; @Value("${student.lastName}") // 从环境变量、配置文件中获取值 private String lastName; @Value("#{12*2}") // #{SpEL} private Integer age; private String gender; private String city; private Teacher teacher; private List hobbys; private Map scores; //注意,为了测试必须重写 toString 和 get,set 方法 }
测试结果
Student{firstName="陈", lastName="一个优秀的废人", age=24, gender="null", city="null", teacher=null, hobbys=null, scores=null}区别
二者区别 | @ConfigurationProperties | @Value |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
从上表可以看见,@ConfigurationProperties 和 @Value 主要有 5 个不同,其中第一个功能上的不同,上面已经演示过。下面我来介绍下剩下的 4 个不同。
松散语法松散语法的意思就是一个属性在配置文件中可以有多个属性名,举个栗子:学生类当中的 firstName 属性,在配置文件中可以叫 firstName、first-name、first_name 以及 FIRST_NAME。 而 @ConfigurationProperties 是支持这种命名的,@Value 不支持。下面以 firstName 为例,测试一下。如下代码:
@ConfigurationProperties
学生类的 firstName 属性在 yml 文件中被定义为 first_name:
student: first_name: 陈 # 学生类的 firstName 属性在 yml 文件中被定义为 first_name lastName: 一个优秀的废人 age: 24 gender: 男 city: 广州 teacher: {name: eses,age: 24,gender: 女} hobbys: [篮球,羽毛球,兵兵球] scores: {java: 100,Python: 99,C++: 99}
学生类:
@Component @ConfigurationProperties(prefix = "student") // 指定配置文件中的 student 属性与这个 bean绑定 public class Student { /** ** * */ //@Value("陈") // 字面量 private String firstName; //@Value("${student.lastName}") // 从环境变量、配置文件中获取值 private String lastName; //@Value("#{12*2}") // #{SpEL} private Integer age; private String gender; private String city; private Teacher teacher; private List hobbys; private Map scores; //注意,为了测试必须重写 toString 和 get,set 方法 }
测试结果:
Student{firstName="陈", lastName="一个优秀的废人", age=24, gender="男", city="广州", teacher=Teacher{name="eses", age=24, gender="女"}, hobbys=[篮球, 羽毛球, 兵兵球], scores={java=100, Python=99, C=99}}
@Value
学生类:
@Component //@ConfigurationProperties(prefix = "student") // 指定配置文件中的 student 属性与这个 bean绑定 public class Student { /** ** * */ //@Value("陈") // 字面量 @Value("${student.firstName}") private String firstName; //@Value("${student.lastName}") // 从环境变量、配置文件中获取值 private String lastName; //@Value("#{12*2}") // #{SpEL} private Integer age; private String gender; private String city; private Teacher teacher; private List hobbys; private Map scores; //注意,为了测试必须重写 toString 和 get,set 方法 }
测试结果:启动报错,找不到 bean。
从上面两个测试结果可以看出,使用 @ConfigurationProperties 注解时,yml 中的属性名为 last_name 而学生类中的属性为 lastName 但依然能取到值,而使用 @value 时,使用 lastName 确报错了。证明 @ConfigurationProperties 支持松散语法,@value 不支持。
SpELSpEL 使用 #{...} 作为定界符 , 所有在大括号中的字符都将被认为是 SpEL , SpEL 为 bean 的属性进行动态赋值提供了便利。
@Value
如上述介绍 @Value 注解使用方法时,有这样一段代码:
@Value("#{12*2}") // #{SpEL} private Integer age;
证明 @Value 是支持 SpEL 表达式的。
@ConfigurationProperties
由于 yml 中的 # 被当成注释看不到效果。所以我们新建一个 application.properties 文件。把 yml 文件内容注释,我们在 properties 文件中把 age 属性写成如下所示:
student.age=#{12*2}
把学生类中的 @ConfigurationProperties 注释打开,注释 @value 注解。运行报错, age 属性匹配异常。
说明 @ConfigurationProperties 不支持 SpEL
JSR303 数据校验@Value
加入 @Length 校验:
@Component @Validated //@ConfigurationProperties(prefix = "student") // 指定配置文件中的 student 属性与这个 bean绑定 public class Student { /** ** * */ //@Value("陈") // 字面量 @Value("${student.first-name}") @Length(min=5, max=20, message="用户名长度必须在5-20之间") private String firstName; //@Value("${student.lastName}") // 从环境变量、配置文件中获取值 private String lastName; //@Value("#{12*2}") // #{SpEL} private Integer age; private String gender; private String city; private Teacher teacher; private List hobbys; private Map scores; }
yaml:
student: first_name: 陈
测试结果:
Student{firstName="陈", lastName="null", age=null, gender="null", city="null", teacher=null, hobbys=null, scores=null}
yaml 中的 firstname 长度为 1 。而检验规则规定 5-20 依然能取到属性,说明检验不生效,@Value 不支持 JSR303 数据校验
@ConfigurationProperties
学生类:
@Component @Validated @ConfigurationProperties(prefix = "student") // 指定配置文件中的 student 属性与这个 bean绑定 public class Student { /** ** * */ //@Value("陈") // 字面量 //@Value("${student.first-name}") @Length(min=5, max=20, message="用户名长度必须在5-20之间") private String firstName; //@Value("${student.lastName}") // 从环境变量、配置文件中获取值 private String lastName; //@Value("#{12*2}") // #{SpEL} private Integer age; private String gender; private String city; private Teacher teacher; private List hobbys; private Map scores; }
测试结果:报错
[firstName],20,5]; default message [用户名长度必须在5-20之间]
校验生效,支持 JSR303 数据校验。
复杂类型封装复杂类型封装指的是,在对象以及 map (如学生类中的老师类以及 scores map)等属性中,用 @Value 取是取不到值,比如:
@Component //@Validated //@ConfigurationProperties(prefix = "student") // 指定配置文件中的 student 属性与这个 bean绑定 public class Student { /** ** * */ //@Value("陈") // 字面量 //@Value("${student.first-name}") //@Length(min=5, max=20, message="用户名长度必须在5-20之间") private String firstName; //@Value("${student.lastName}") // 从环境变量、配置文件中获取值 private String lastName; //@Value("#{12*2}") // #{SpEL} private Integer age; private String gender; private String city; @Value("${student.teacher}") private Teacher teacher; private List hobbys; @Value("${student.scores}") private Map scores; }
这样取是报错的。而上文介绍 @ConfigurationProperties 和 @Value 的使用方法时已经证实 @ConfigurationProperties 是支持复杂类型封装的。也就是说 yaml 中直接定义 teacher 以及 scores 。 @ConfigurationProperties 依然能取到值。
怎么选用?如果说,只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用 @Value;比如,假设现在学生类加多一个属性叫 school 那这个属性对于该校所有学生来说都是一样的,但防止我这套系统到了别的学校就用不了了。那我们可以直接在 yml 中给定 school 属性,用 @Value 获取。当然上述只是举个粗暴的例子,实际开发时,school 属性应该是保存在数据库中的。
如果说,专门编写了一个 javaBean 来和配置文件进行映射,我们就直接使用 @ConfigurationProperties。
完整代码https://github.com/turoDog/Demo/tree/master/springboot_val_conpro_demo
如果觉得对你有帮助,请给个 Star 再走呗,非常感谢。
后语如果本文对你哪怕有一丁点帮助,请帮忙点好看。你的好看是我坚持写作的动力。
另外,关注之后在发送 1024 可领取免费学习资料。
资料详情请看这篇旧文:Python、C++、Java、Linux、Go、前端、算法资料分享
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/77464.html
微信公众号:一个优秀的废人。如有问题,请后台留言,反正我也不会听。 前言 最近有跳槽的想法,所以故意复习了下 SpringBoot 的相关知识,复习得比较细。其中有些,我感觉是以前忽略掉的东西,比如 @Value 和 @ConfigurationProperties 的区别 。 如何使用 定义两个对象,一个学生对象,对应着一个老师对象,代码如下: @ConfigurationProperties ...
摘要:全局配置文件默认为下的,另外它还可以重命名为格式即对着两种格式均支持。其中每个环境的数据库地址服务器端口等等配置都会不同,如果在为不同环境打包时都要频繁修改配置文件的话,那必将是个非常繁琐且容易发生错误的事。 SpringBoot全局配置文件默认为src/main/resources下的application.properties,另外它还可以重命名为.yml格式(即SpringBoo...
摘要:采纳了建立生产就绪应用程序的观点。优先于配置的惯例,旨在让您尽快启动和运行。启动工程,访问我们会发现配置文件信息读到了。三自定义配置文件上面介绍的是我们都把配置文件写到中。源码下载五参考文献干货系列二配置文件解析属性配置文件详解 springboot采纳了建立生产就绪Spring应用程序的观点。 Spring Boot优先于配置的惯例,旨在让您尽快启动和运行。在一般情况下,我们不需要做...
摘要:这里有一个参数,主要是用来指定该配置项在配置文件中的前缀。创建一个配置类,里面没有显式声明任何的,然后将刚才创建的导入。创建实现类,返回的全类名。创建实现类,实现方法直接手动注册一个名叫的到容器中。前言 小伙伴们是否想起曾经被 SSM 整合支配的恐惧?相信很多小伙伴都是有过这样的经历的,一大堆配置问题,各种排除扫描,导入一个新的依赖又得添加新的配置。自从有了 SpringBoot 之后,咋...
摘要:不同的环境之间的配置存在覆盖关系。提供了一种统一的方式来管理应用的配置,允许开发人员使用属性文件文件环境变量和命令行参数来定义优先级不同的配置值。比如命令行参数的优先级被设置为最高。 一.关于Spring Boot的配置 Spring Boot 对于开发人员最大的好处在于可以对 Spring 应用进行自动配置。Spring Boot 会根据应用中声明的第三方依赖来自动配置 Spring...
阅读 1524·2021-11-16 11:44
阅读 7352·2021-09-22 15:00
阅读 4405·2021-09-02 10:20
阅读 1881·2021-08-27 16:20
阅读 2334·2019-08-26 14:00
阅读 2888·2019-08-26 11:44
阅读 1590·2019-08-23 18:33
阅读 1833·2019-08-22 17:28