3.4 自定义配置
我们可以直接在application.yml文件中定义我们自己的配置,问题是如何使用定义的配置。在前面的章节中,我们使用过Environment来读取配置,如果属性较多,这种方式会带来混乱。Spring提供了@Value注解,从而可以让我们的业务代码去读取配置,而Spring Boot提供了一种更优雅的方式来获取配置。这一节我们先回顾Spring的@Value注解,再学习Spring Boot的配置使用。
3.4.1 @Value注解
在使用Spring的时候,如果要在程序中使用属性,则可以定义一个属性类,再使用@Value注解修饰相应的属性即可,请见代码清单3-21。
代码清单3-21:codes\03\3.3\prop-test\src\main\java\org\crazyi\boot\c3\value\ValueProp.java
@Component public class ValueProp { @Value("${jdbc.url}") private String jdbcUrl; public String getJdbcUrl() { return jdbcUrl; } }
可将代码清单3-21中的ValueProp类称为属性映射类,该类将会注册到Spring容器中。在使用@Value注解时,需要设置属性值的key,本例中的key为jdbc.url,对应到application.yml文件中,应当这样配置:
jdbc: url:value
接下来,编写控制器,来使用ValueProp的属性,请见代码清单3-22。
代码清单3-22:codes\03\3.3\prop-test\src\main\java\org\crazyi\boot\c3\PropController.java
@RestController public class PropController { @Autowired private ValueProp valueProp; @GetMapping(value = "/value", produces = MediaType.APPLICATION_JSON_VALUE) public ValueProp value() { return valueProp; } }
直接在控制器中注入ValueProp实例,value方法返回ValueProp实例。启动服务器后(本例为codes\03\3.3\prop-test\src\main\java\org\crazyi\boot\c3\PropApp.java),在浏览器中输入:http://localhost:8080/value,可以看到浏览器输出如下:
{"jdbcUrl":"localhost:3306"}
使用@Value注解,使得属性的获取更加面向对象。使用属性时也不需要关心属性的key,但@Value注解会带来一个问题,即在映射属性时,需要传入“jdbc.url”,如果jdbc下面有多个属性,就会造成代码的冗余。对这种情况,可以使用Spring Boot的配置。
3.4.2 定义属性映射对象
假设我们在配置文件中定义一些JDBC的属性,请见代码清单3-23。
代码清单3-23:codes\03\3.3\prop-test\src\main\resources\application.yml
jdbc: url: localhost:3306 user: root password: 123456 db: name: mysql version: 1.0 roles: - manager - client
与使用@Value注解类似,新建一个属性映射类,请见代码清单3-24。
代码清单3-24:codes\03\3.3\prop-test\src\main\java\org\crazyi\boot\c3\MyProp.java
@ConfigurationProperties(prefix = "jdbc") public class MyProp { private String url; private String user; private String password; private Database db; ...省略setter和getter方法 public static class Database { private String name; private String version; private List<String> roles; ...省略setter和getter方法 } }
在代码清单3-24中,定义了属性映射类MyProp,这个类使用了@ConfigurationProperties注解进行修饰,并且声明了该类的配置前缀为“jdbc”,这样在使用MyProp的getUrl方法时,就可以获取配置文件中的“jdbc.url”属性值。需要注意的是db属性,它是Database类型,Database类型下的roles属性是一个字符串集合,在配置时,需要使用以下格式:
jdbc: db: roles: - manager - client
以上的配置会为Database的roles属性加入manager与client两个常量。以上在Spring Boot中自定义了属性,下面,讲解如何使用这些属性。
3.4.3 使用配置
建立了属性映射类后,我们还要告诉Spring容器,这里有一个自定义的属性映射对象。新建一个配置类,请见代码清单3-25。
代码清单3-25:codes\03\3.3\prop-test\src\main\java\org\crazyi\boot\c3\MyConfig.java
@Configuration @EnableConfigurationProperties(value = MyProp.class) public class MyConfig { }
在前面定义属性映射类时,使用了@ConfigurationProperties注解来修饰,但这还不能让Spring容器发现它的存在,还要使用代码清单3-25中的@EnableConfigurationProperties注解,这个注解会让Spring容器去注册属性映射对象,本例中的MyProp对象,将会作为一个bean被放到Spring容器中。编写一个控制器使用MyProp对象,请见代码清单3-26。
代码清单3-26:codes\03\3.3\prop-test\src\main\java\org\crazyi\boot\c3\PropController.java
@RestController public class PropController { @Autowired private MyProp prop; @GetMapping(value = "/hello", produces = MediaType.APPLICATION_JSON_VALUE) public MyProp hello() { return prop; } }
直接在控制器中使用@Autowird注入一个MyProp实例,在hello方法中,会把这个MyProp实例作为JSON字符串返回。启动服务器(PropApp.java),在浏览器中访问:http://localhost:8080/hello,浏览器输出如下:
{"url":"localhost:3306", "user":"root", "password":"123456", "db":{"name":"mysql","version":"1.0", "roles":["manager", "client"]}}
根据输出结果可知,我们所设计的属性映射对象(MyProp),已经可以被控制器使用。Spring Boot的这种方式,相对于@Value注解来说,在Java类中可以减少配置的冗余,同时也增强了配置的可读性,使用起来更加简便。
3.4.4 属性自动识别
假设有以下属性映射类:
@ConfigurationProperties(prefix = "jdbc") public class MyProp { private String userName; }
前缀是jdbc,属性为userName,如果使用了@ConfigurationProperties,那么以下的几种配置都会被识别,并且被设置到MyProp类的userName中:
jdbc.userName
jdbc.user-name
jdbc.user_name
JDBC_USER_NAME
属性自动识别,官方文档称其为“relaxed binding”。关于自定义配置就讲解到这里,这里所介绍的配置知识,基本上可以满足实际环境的需要。