1.获取数据源 DynamicDataSource.java
package com.test.data.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 获取数据源
* Created by guanguan on 2017/8/22.
*/
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataHolder.getDataSource();
}
}
2.DynamicDataHolder.java一个自定义的操作数据源的类
package com.test.data.config;
import com.test.data.enums.DataSourceType;
/**
* 数据源操作的类
* Created by guanguan on 2017/8/22.
*/
public class DynamicDataHolder {
//线程本地环境
private static final ThreadLocal<DataSourceType> dataSources = new ThreadLocal<DataSourceType>();
//设置数据源
public static void setDataSources(DataSourceType dataSourceType){
dataSources.set(dataSourceType);
}
//获取数据源
public static DataSourceType getDataSource(){
return dataSources.get();
}
//清除数据源
public static void clearDataSource(){
dataSources.remove();
}
}
3.MyBatisConfig.java
package com.test.data.config;
import com.test.data.enums.DataSourceType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
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;
import java.util.HashMap;
/**
* Created by guanguan on 2017/7/20.
*/
@Configuration
@MapperScan("com.test.data.dao") //扫描到dao层实现mybatis的xml文件与dao层的文件进行映射绑定
public class MybatisConfig {
/**
* 创建数据源 manage
* @return
* @throws Exception
*/
@Bean
@ConfigurationProperties(prefix = "manage") //从yml配置文件里读取,如果配置在spring路径下,可改为spring.manage
public DataSource manageDataSource() throws Exception{
return DataSourceBuilder.create().build();
}
/**
* 创建数据源 test
* @return
* @throws Exception
*/
@Bean
@ConfigurationProperties(prefix = "test")//从yml配置文件里读取,指定配置项的前缀
public DataSource testDataSource() throws Exception{
return DataSourceBuilder.create().build();
}
/**
*
* @return
* @throws Exception
*/
@Bean
@Primary
public DynamicDataSource dataSource(@Qualifier("manageDataSource") DataSource manageDataSource,
@Qualifier("testDataSource") DataSource testDataSource){
HashMap<Object,Object> targetDataSources = new HashMap<Object,Object>();
targetDataSources.put(DataSourceType.manage,manageDataSource);
targetDataSources.put(DataSourceType.test,testDataSource);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources); //该方法是继承的AbstractRoutingDataSource的方法
dataSource.setDefaultTargetDataSource(manageDataSource); //设置默认的数据源
return dataSource;
}
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mybatis/*/*.xml"));
return sqlSessionFactoryBean.getObject();
}
}
//项目启动时,会运行加载该类,从yml的配置中自动分配数据源,到DynamicDataSource实体中
以上为启动是分配的多数据源,启动时将配置文件yml中的数据源配置放于DynamicDataSource中
将数据源放于sqlSessionFactoryBean中
4.DataSourceType.java文件,枚举,数据源的命名
package com.test.data.enums;
/**
* Created by guanguan on 2017/8/22.
*/
public enum DataSourceType {
manage,test
}
4.拦截,并自动分配数据源 DataSourceAspect.java
package com.test.data.interceptor;
import com.test.data.config.DynamicDataHolder;
import com.test.data.enums.DataSourceType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
* Created by guanguan on 2017/8/22.
*/
@Aspect //aop切面拦截
@Component //组件,启动时加载
public class DataSourceAspect {
/**
* 在通用方法中拦截操作数据库的方法
* @param point
*/
@Before("execution(* com.test.data.service.Services.*(..))")
public void setDataSourceKeyByPublic(JoinPoint point){
String targetStr = point.getTarget().toString();
setDataSourceKey(targetStr);
}
@Before("execution(* com.test.data.service.*.*.*(..))")
public void setDataSourceKeyByPrivate(JoinPoint point){
String targetStr = point.getTarget().toString();
setDataSourceKey(targetStr);
}
private void setDataSourceKey(String targetStr){
if(targetStr.contains("manage")){
DynamicDataHolder.setDataSources(DataSourceType.manage);
}else if(targetStr.contains("test")){
DynamicDataHolder.setDataSources(DataSourceType.test);
}
}
}
5.application.yml文件
server:
port: 8389
manage:
url: jdbc:mysql://127.0.0.1/manage?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&autoReconnect=true
username: upgrade
password: upgrade
driverClassName: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
validation-query: select 'x'
test-while-idle: true
test:
url: jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&autoReconnect=true
username: upgrade
password: upgrade
driverClassName: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
validation-query: select 'x'
test-while-idle: true
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
logging:
level.com.test.data: debug
6.controller.java校验多数据源的方法,查询两个库的不同的表的数据
package com.test.data.controller;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.test.data.model.manage.LoginLog;
import com.test.data.model.test.User;
import com.test.data.service.manage.LoginLogService;
import com.test.data.service.test.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.List;
/**
* Created by guanguan on 2017/7/20.
*/
@Controller
public class controller {
@Autowired
UserService userService;
@Autowired
LoginLogService loginLogService;
@RequestMapping("/")
@ResponseBody
public String index() {
List<User> userList = userService.findBy(new HashMap<Object, Object>());
List<LoginLog> loginLogList = loginLogService.findBy(new HashMap<Object, Object>());
return JSON.toJSONString(userList)+JSON.toJSONString(loginLogList);
}
}
7.查询结果:(由于没写前端页面展示为string的返回结果)
输入:http://localhost:8389/
8.pom.xml文件要加入aop依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
8.整个工程的布局:
见github地址:
https://github.com/gholly/springboot-multi-datasource