一、介绍
1、在springboot项目中,都是将数据库连接池配置放在application.properties中,如果我们需要修改连接池配置,改完配置之后需要提交代码、打包、部署,这样就很麻烦,如果可以将连接池配置放在apollo、zookeeper、redis里是不是修改之后只需要重新部署就可以了,省去前两步;
2、案例中只是从Property配置文件中读取数据源配置。
PropertyPlaceholderConfigurer是干什么的?
PropertyPlaceholderConfigurer是spring的后置处理器,它的作用就是读取Property配置文件,将XML和java代码中有${key}占位符的替换掉,其中key的值就是Property中配置的key
二、案例
1、pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cn.dl</groupId>
<artifactId>springbootdemotest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springbootdemotest</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、TaskJobBean
package com.cn.dl.bean;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Created by yanshao on 2018/12/11.
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TaskJobBean {
//todo 实际开发还有很多属性!!!
private String jobName;
private String jobClassName;
private String jobCron;
}
3、TaskJobMapper
package com.cn.dl.mapper;
import com.cn.dl.bean.TaskJobBean;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* Created by yanshao on 2018/12/11.
*/
@Mapper
public interface TaskJobMapper {
@Select("select job_name,job_class_name,job_cron from task_job_schedule")
List<TaskJobBean> findAllTaskJob();
}
4、PropertyPlaceholderConfigurerCustomize
这个类是这个案例的重点,先从/config/springboot.properties读取配置,保存到PropertiesLoaderSupport类localProperties中
package com.cn.dl.config;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* 加载配置文件
* Created by yanshao on 2018/12/11.
*/
@Component
public class PropertyPlaceholderConfigurerCustomize extends PropertyPlaceholderConfigurer {
public PropertyPlaceholderConfigurerCustomize(){
InputStream in = PropertyPlaceholderConfigurerCustomize.class.getResourceAsStream("/config/springboot.properties");
Properties properties = new Properties();
try {
properties.load(in);
super.setProperties(properties);
} catch (IOException e) {
e.printStackTrace();
}
}
}
这段代码的作用相当于下面这段xml配置
<bean id= "placeholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<property name="location" >
<value>classpath:/config/springboot.properties</value >
</property>
</bean>
5、ReadApplicationContext:加载applicationContext-*.xml配置文件
package com.cn.dl.config;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.ImportResource;
/**
* 加载applicationContext-*.xml配置文件
* Created by yanshao on 2018/12/11.
*/
// TODO: 2018/12/11 @ImportResource不能单独使用
@SpringBootConfiguration // TODO: 2018/12/18 也可以用@Configuration
@ImportResource(locations = {"classpath*:applicationContext-*"})
public class ReadApplicationContext {
}
6、ServiceTest:验证PropertyPlaceholderConfigurerCustomize类是否成功加载到/config/springboot.properties配置文件
package com.cn.dl.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* Created by yanshao on 2018/12/18.
*/
@Service
public class ServiceTest {
//业务名称
@Value("${serviceName}")
private String serviceName;
//业务类型
@Value("${serviceType}")
private String serviceType;
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getServiceType() {
return serviceType;
}
public void setServiceType(String serviceType) {
this.serviceType = serviceType;
}
@Override
public String toString() {
return "ServiceTest{" +
"serviceName='" + serviceName + '\'' +
", serviceType='" + serviceType + '\'' +
'}';
}
}
7、ServiceController
package com.cn.dl.controller;
import com.cn.dl.mapper.TaskJobMapper;
import com.cn.dl.service.ServiceTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* Created by yanshao on 2018/12/18.
*/
@RestController
@RequestMapping("/service")
public class ServiceController {
@Autowired
ServiceTest serviceTest;
@Autowired
TaskJobMapper taskJobMapper;
@GetMapping("/test")
public String serviceTest(){
return serviceTest.toString();
}
@GetMapping("/job")
public List findAll(){
return taskJobMapper.findAllTaskJob();
}
}
8、/config/springboot.properties内容
user.name=tiger
user.age=13
user.address=shanghai
serviceName=messageSystem
serviceType=save
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tiger_base?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&generateSimpleParameterMetadata=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.max-idle=10
spring.datasource.max-wait=60000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validationQuery=select 'x'
9、applicationContext-dataSource.xml
注意:这块配置就是之前在application.properties中那些配置内容
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="masterDatasource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close" >
<property name="dbType" value="mysql"/>
<property name="url" value="${spring.datasource.url}"/>
<property name="driverClassName" value="${spring.datasource.driver-class-name}"/>
<property name="username" value="${spring.datasource.username}"/>
<property name="password" value="${spring.datasource.password}"/>
<property name="initialSize" value="${spring.datasource.initial-size}"/>
<property name="maxWait" value="60000"/>
</bean>
</beans>
三、测试
1、postMan调:127.0.0.1:8080/service/test
注意:看到messageSystem和save说明我们可以正常读取配置!
2、调127.0.0.1:8080/service/job
注意:表中有3条数据,调用接口返回下面3条数据,说明连接池配置成功
[
{
"jobName": "jobA",
"jobClassName": "com.cn.dl.task.JobA",
"jobCron": "0/5 * * * * ? *"
},
{
"jobName": "jobB",
"jobClassName": "com.cn.dl.task.JobB",
"jobCron": "0 0 04 * * ? *"
},
{
"jobName": "jobC",
"jobClassName": "com.cn.dl.task.JobC",
"jobCron": "0/30 * * * * ? *"
}
]
四、总结
配置放在那里,关键是要看是否方便我们维护管理,在代码里修改配置麻烦而且有时候容易出错。
下面两篇是从apollo读取配置的案例:
https://blog.csdn.net/qq_31289187/article/details/84346529
https://blog.csdn.net/qq_31289187/article/details/83003771