Spring Boot 2+Thymeleaf企业应用实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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”。关于自定义配置就讲解到这里,这里所介绍的配置知识,基本上可以满足实际环境的需要。