springboot弱化配置的特性让属性配置文件的使用也更加便捷,它默认支持
对application.properties或application.yml属性配置文件处理,即在
application.properties或application.yml文件中添加属性配置,可以使用@Value
注解将属性值注入到beans中,或使用@ConfigurationProperties注解将属性值绑定到结构化的beans中,本篇将介绍springboot使用YAML属性配置。
需求&背景
YAML是JSON的一个超集,是一种方便的定义层次配置数据的格式,结构层次上清晰明了,配置简单易读、易用。要想使用YAML作为属性配置文件,需要将SnakeYAML库添加到classpath下,Spring Boot对SnakeYAML库也做了集成,例如使用spring-boot-starter-web或spring-boot-starter都会自动添加SnakeYAML库到classpath下。
此篇我们就基于自定义yaml配置实现数据库简单的查询操作。
一)新建应用&添加依赖
新建一个maven项目,除了添加springboot的基础依赖还要添加数据库操作相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jdbcTemplate -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!-- mysql connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
二)添加数据库属性配置文件
在src/resources目录下添加druid.yml文件,并添加数据库配置属性:
#数据库设置
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://local:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=true
username: username
password: password
initialSize: 5
minIdle: 1
maxActive: 50
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: false
filters: stat,wall,log4j
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
yaml多个层级之间建议使用两个空格(不建议使用tab代替,有可能根本不支持)。此例中spring:是一级,datasource是二级driverCalssName是三级属性,其实就等价于properties配置文件中的spring.datasource.driverClassName。
三)数据库配置&业务代码
1.数据源配置
和之前使用properties属性配置类似,将yaml配置文件引入到配置类就能使用配置项:
@Configuration
@PropertySource(value = "classpath:druid.yml")
@ConfigurationProperties(prefix = "spring.datasource")
public class DruidConfiguration {
@Bean(destroyMethod = "close", initMethod = "init",name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
}
2.编写业务代码
使用jdbcTemplate完成dao层数据库操作:
@Repository
@Slf4j
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<User> listAll() {
List<User> list = this.jdbcTemplate.query("select * from User", BeanPropertyRowMapper.newInstance(User.class));
if(null == list || list.isEmpty()) {
return Collections.emptyList();
}
log.info("UserDao.listAll find list size={}",list.size());
return list;
}
}
controller层直接使用dao完成数据查询:
@RestController
@RequestMapping("/user")
public class IndexController {
@Autowired
private UserDao userDao;
@GetMapping("/list")
public Object list() {
return this.userDao.listAll();
}
}
四)测试&踩坑
运行Main启动应用:
@SpringBootApplication
public class Demo8Application
{
public static void main(String[] args) {
SpringApplication.run(Demo8Application.class, args);
}
}
应用启动报错:
根据报错信息简单分析一下,数据源dataSource无法创建,原因是填充数据库连接信息的时候报错,没有找到相关的属性,往前反推一下,为什么没有相关属性?那肯定是因为druid.yml属性文件中的配置读取失败。查了一番资料之后,发现两篇文章讲的比较好一点:
https://tomoya92.github.io/2017/11/10/spring-boot-self-yml/
https://mdeinum.github.io/2018-07-04-PropertySource-with-yaml-files/
结论就是现在版本的springboot默认已经不支持yaml自定义配置文件了,那如果你有一些特殊的需求仍需要使用的话,只能自己实现了,目前有两种解决方案:
1.自定义PropertySourcesPlaceholderConfigurer
在应用的任意位置添加如下代码(建议在配置类中):
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("druid.yml"));
configurer.setProperties(yaml.getObject());
return configurer;
}
重新启动应用后没有报错,但是这样做有一个缺点,在有多个自定义yaml文件的时候需要修改配置。
2.自定义PropertySourceFactory
创建自定义配置类YamlPropertySourceFactory实现PropertySourceFactory接口:
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
Properties propertiesFromYaml = loadYamlIntoProperties(resource);
String sourceName = name != null ? name : resource.getResource().getFilename();
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
}
private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException {
try {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
} catch (IllegalStateException e) {
// for ignoreResourceNotFound
Throwable cause = e.getCause();
if (cause instanceof FileNotFoundException)
throw (FileNotFoundException) e.getCause();
throw e;
}
}
}
在数据源配置类中的@PropertySource注解中添加factory = YamlPropertySourceFactory.class,也就是使用我们自己定义的
PropertySourceFactory解析yaml配置文件:
重新启动应用成功:
启动应用后浏览器输入http://localhost:8080/user/list:
请求能够被正常的接收和处理,也就是说明我们使用的自定义yaml配置文件已经生效。
总结
通过上边的编码测试,我们实现了springboot使用yaml配置文件完成数据库查询操作,中间也遇到了自定义yaml配置文件无法解析的问题,两种方案中推荐使用第二种(全部配置),对于properties和yaml配置孰优孰劣,网上很多文章大多一边倒的认为yaml要比properties好,但是使用的时候还是要根据场景和团队人员的开发习惯,不建议一味的把properties文件用yaml替代,否则可能出现意想不到的问题。
本文分享自 PersistentCoder 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!