1、配置文件 application-dev.yml 设置
spring:
datasource:
ds1:
url: jdbc:mysql://10.126.89.86:58885/xxxx?useSSL=false
username: xxxx
password: xxxxx
driver-class-name: com.mysql.jdbc.Driver
ds2:
url: jdbc:mysql://10.126.89.86:58885/xxx?useSSL=false
username: xxxx
password: xxxxxx
driver-class-name: com.mysql.jdbc.Driver
mybatis:
mapper-locations: classpath:mybatis/mapper/*.xml
type-aliases-package: com.data.pcv.dao.model
config-locations: classpath:mybatis/mybatis-config.xml
configuration:
map-underscore-to-camel-case: true
use-generated-keys: true
2、配置Druid 多个数据源和 Druid监控Servlet
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DruidConfig {
private static final Logger log = LoggerFactory.getLogger(DruidConfig.class);
//数据源一
@Bean(name = "ds1DataSource" )
@ConfigurationProperties(prefix="spring.datasource.ds1")
public DruidDataSource ds1DataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
//数据源二
@Bean(name = "ds2DataSource" )
@ConfigurationProperties(prefix="spring.datasource.ds2")
public DruidDataSource ds2DataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
@Bean
public ServletRegistrationBean druidServlet() {
log.info("init Druid Servlet Configuration ");
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(new StatViewServlet());
servletRegistrationBean.addUrlMappings("/druid/*");
Map initParameters = new HashMap<>();
initParameters.put("loginUsername", “admin");// 用户名
initParameters.put("loginPassword", “admin");// 密码
initParameters.put("allow","");
initParameters.put("resetEnable", "false");// 禁用HTML页面上的“Reset All”功能
//initParameters.put("allow", allowIp); // IP白名单 (没有配置或者为空,则允许所有访问)
//initParameters.put("deny", "");// IP黑名单 (存在共同时,deny优先于allow)
servletRegistrationBean.setInitParameters(initParameters);
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
3、创建 动态数据源DynamicDataSource 类继承AbstractRoutingDataSource抽象类
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal contextHolder = new ThreadLocal<>();
/**
* 配置DataSource, defaultTargetDataSource为主数据库
*/
public DynamicDataSource(DataSource defaultTargetDataSource, Map
4、动态数据源配置注入,设置事务管理器和SQLSessionFactory
import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DynamicDataSourceConfig {
//pagehelper 插件
@Autowired
private PageInterceptor pageInterceptor;
//Spring环境上下文
@Autowired
private Environment environment;
//注入mybatis 配置
@Bean
@ConfigurationProperties(prefix = "mybatis.configuration")
public org.apache.ibatis.session.Configuration globalConfiguration() {
return new org.apache.ibatis.session.Configuration();
}
//配置主数据源
@Bean
@Primary
public DynamicDataSource dynamicDataSource( DruidDataSource ds1DataSource,
DruidDataSource ds2DataSource) {
Map
5、自定义注解 并设置默认的数据源
import java.lang.annotation.*;
/**
* 多数据源注解默认pcv
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value() default Consts.DATASOURCE_PCV;
}
6、切面
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class DataSourceAspect implements Ordered {
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 切点: 所有配置 DataSource 注解的方法
*/
@Pointcut("@annotation(com.data.pcv.annotation.DataSource)")
public void dataSourcePointCut() {}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource ds = method.getAnnotation(DataSource.class);
// 通过判断 DataSource 中的值来判断当前方法应用哪个数据源
DynamicDataSource.setDataSource(ds.value());
System.out.println("当前数据源: " + ds.value());
logger.debug("set datasource is " + ds.value());
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
logger.debug("clean datasource");
}
}
@Override
public int getOrder() {
return 1;
}
}
7、启动类 排除 DataSource自动配置
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Import;
@Import({DynamicDataSourceConfig.class})
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class PCVApplication {
public static void main(String[] args) {
SpringApplication.run(PCVApplication.class, args);
}
}
8、使用案例
普通方法使用默认的DataSource,若需要使用另一个DataSource,则在Service实现方法上加注解 @DataSource(指定的数据源)
@Service
public class DavinciUserServiceImp implements DavinciUserService {
@Autowired
DavinciUserModelMapper davinciUserModelMapper;
@DataSource(Consts.DATASOURCE_DAVINCI)
@Override
public DavinciUserModel getByUserName(String username){
return davinciUserModelMapper.selectByUserName(username);
}
@DataSource(Consts.DATASOURCE_DAVINCI)
@Override
public int insertSelective(DavinciUserModel insertModel) {
return davinciUserModelMapper.insertSelective(insertModel);
}
}