第一次写这种东西,就是自己做出来了之后,在一步一步发上来,可能逻辑有点乱,看的时候可能需要费点心.
工具 : idea
框架 : ssm
我做的项目需要再新表和旧表中切换,实现层的业务逻辑是相同的,但是获取的表不一样,想要不修改代码,就修改properties文件来决定controller层调用的实现层是哪一个.
先从.yml文件开始吧,因为这里的新表旧表不在一个服务器上面,所以我们需要多个连接来连接多个数据库
spring:
datasource:
primary:
jdbc-url: jdbc:sqlserver://10.0.0.111:1433;DatabaseName=HISDB
username: sa
password: rjhis
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
initial-size: 1
min-idle: 1
max-active: 20
test-on-borrow: true
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-While-Idle: true
test-on-return: false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
filters: log4j,wall,mergeStat
secondary:
jdbc-url: jdbc:sqlserver://10.0.0.104\:1433;DatabaseName=mzys
username: rjhis
password: rjhis
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
initial-size: 1
min-idle: 1
max-active: 20
test-on-borrow: true
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-While-Idle: true
test-on-return: false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
filters: log4j,wall,mergeStat
third:
jdbc-url: jdbc:sqlserver://10.0.0.111\MSSQLSERVER2008;DatabaseName=zxhis
username: sa
password: abc.123
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
initial-size: 1
min-idle: 1
max-active: 20
test-on-borrow: true
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-While-Idle: true
test-on-return: false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
filters: log4j,wall,mergeStat
在yml配置完之后,需要一个工具类
import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.reijing.his.rest.modular.dao.mapping.primary", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setDataSource(dataSource);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
configuration.setJdbcTypeForNull(JdbcType.NULL);
sqlSessionFactory.setConfiguration(configuration);
sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com/reijing/his/rest/modular/dao/mapping/primary/*.xml"));
sqlSessionFactory.setPlugins(new Interceptor[]{new PaginationInterceptor()});
return sqlSessionFactory.getObject();
}
@Bean(name = "primarySqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
这个是primary 的工具类 ,剩下的两个雷同
在存放Mapper文件的类中,分出三个文件夹,sql调用那个库的表就放入那个文件夹
这样的话就可以调用不同服务器的数据库了
接下里就写个测试,看看能不能调用
service
public interface Test {
String test1();
String test2();
}
impl
@Service
@Transactional
public class TestImpl implements Test {
@Autowired
private TestMapper getGetMaxIdMapper;
@Autowired
private TestMapper1 testMapper1;
private static TestImpl dynamicProxy;
@PostConstruct
public void init() {
dynamicProxy = this;
}
@Override
public String test1() {
Integer test = dynamicProxy.getGetMaxIdMapper.test();
if(test>0){
return "查询到"+test;
}
return "失败";
}
@Override
public String test2() {
Integer test = dynamicProxy.testMapper1.test();
if(test>0){
return "查询到"+test;
}
return "失败";
}
}
private static TestImpl dynamicProxy;
@PostConstruct
public void init() {
dynamicProxy = this;
}
这个是一定需要的,在调用mapper前需要加上dynamicProxy.
实现层的mapper 是我随便找了两个库然后查询两个库内的表,主要为了测试一下是否可以使用
controller
@Api(value = "test",description = "test")
@RestController
public class TestController {
@Autowired
private Test test;
@ApiOperation(value = "11111", notes = "")
@PostMapping("/test/io1")
public Object selectset() throws Exception {
//获取配置文件
String filePath = System.getProperty("user.dir") + "/io-config.properties";
InputStream br = new BufferedInputStream(new FileInputStream(filePath));//读取model外配置文件信息
java.util.Properties props = new java.util.Properties();//读取配置文件方法
props.load(br);//读取
String settleAccounts_Method = (String)props.get("test_m");//根据配置文件内的字段获取字段内信息(调用类内的方法)
String settleAccounts_Path = (String)props.get("test_p");//根据配置文件内的字段获取字段内信息(调用类的路径)
Class aClass = Class.forName(settleAccounts_Path);//获取路径内的类
Method[] methods = aClass.getMethods();
for (Method method : methods) {//遍历类中的方法
if(method.getName().equals(settleAccounts_Method)){//比较是否与配置文件内的方法名是否相同 , 相同则调用
Method declaredMethod = aClass.getDeclaredMethod(settleAccounts_Method);
return declaredMethod.invoke(aClass.newInstance());
}
}
return null;
}
}
因为我们的配置文件 会放在jar包的外层 , 所以获取的地址就是jar包外的properties
properties
test_m=test1
test_p=com.reijing.his.io.modular.service.impl.TestImpl
也就说,当我的test_m=test1 的时候,我们调用的就是test1的方法
我们可以试着跑一下我们的项目,测试一下
打开脚本就可以启动了(我偷懒,把东西直接放在桌面了)
在swagger上测一下
当配置文件路径test1 时 我们调用的是这张表
在项目还在运行的时候 ,我们直接修改配置文件, 把test_m 改成test2
这样的话我们就做到了,动态修改实现的方法
其中哪里有问题,希望评论,私信什么的告诉我