基于上个项目完成数据源配置。
1、修改pom.xml文件,加入AOP和Processor
org.springframework.boot
spring-boot-starter-aop
org.springframework.boot
spring-boot-configuration-processor
true
2、修改application.properties文件
#修改tomcat端口为80
server.port=80
#设置Tomcat编码
server.tomcat.uri-encoding=UTF-8
#MyBatis配置
mybatis.config-location=classpath:mybatis/mybatis-cfg.xml
mybatis.type-aliases-package=com.example.demo.pojo
mybatis.mapper-locations=classpath*:/com/example/demo/mapper/*.xml
#数据库连接池配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.initial-size = 5
spring.datasource.druid.max-active = 20
spring.datasource.druid.min-idle = 5
spring.datasource.druid.max-wait= 30000
#数据库1配置
spring.datasource.one.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.one.url=jdbc:mysql://127.0.0.1:3306/database_one
spring.datasource.one.username=root
spring.datasource.one.password=root
#数据库2配置
spring.datasource.two.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.two.url=jdbc:mysql://127.0.0.1:3306/database_two
spring.datasource.two.username=root
spring.datasource.two.password=root
3、编写切面DynamicDataSourceAspect.java
package com.example.demo.common.aspect;
import java.lang.reflect.Method;
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.springframework.stereotype.Component;
import com.example.demo.common.config.DynamicDataSourceHolder;
import com.example.demo.common.config.TargetDataSource;
/**
*
* @ClassName: DynamicDataSourceAspect
* @Description: TODO(定义切面用于切换数据源)
* @author willdas
* @date 2018年9月12日 下午5:51:46
*
*/
@Aspect
@Component
public class DynamicDataSourceAspect {
@Pointcut("@annotation(com.example.demo.common.config.TargetDataSource)")
public void point() {
}
@Pointcut("execution(public * com.example.demo.*.service..*.*(..))")
public void excudeService() {
}
@Around(value = "point()&&excudeService()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method targetMethod = methodSignature.getMethod();
if (targetMethod.isAnnotationPresent(TargetDataSource.class)) {
String targetDataSource = targetMethod.getAnnotation(TargetDataSource.class).dataSource();
DynamicDataSourceHolder.setDataSource(targetDataSource);
}
Object result = pjp.proceed();// 执行方法
DynamicDataSourceHolder.clearDataSource();
return result;
}
}
4、编写DruidDataSourceConfig.java
package com.example.demo.common.config;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
/**
*
* @ClassName: DruidDataSourceConfig
* @Description: TODO(多数据源切换)
* @author willdas
* @date 2018年9月11日 下午2:50:12
*
*/
@Configuration
@MapperScan(basePackages = "com.example.demo.*.dao", sqlSessionFactoryRef = "sqlSessionFactory")
public class DruidDataSourceConfig {
/**
* 配置别名
*/
@Value("${mybatis.type-aliases-package}")
private String typeAliasesPackage;
/**
* 配置mapper的扫描,找到所有的mapper.xml映射文件
*/
@Value("${mybatis.mapper-locations}")
private String mapperLocations;
/**
* 加载全局的配置文件
*/
@Value("${mybatis.config-location}")
private String configLocation;
/**
* 数据源1
*/
@Bean(name = "oneDataSource")
@ConfigurationProperties(prefix = "spring.datasource.one")
public DataSource dataSourceOne() {
return DruidDataSourceBuilder.create().build();
}
/**
* 数据源2
*/
@Bean(name = "twoDataSource")
@ConfigurationProperties(prefix = "spring.datasource.two")
public DataSource dataSourceTwo() {
return DruidDataSourceBuilder.create().build();
}
/**
* 数据源管理
*/
@Bean
public DataSource dynamicDataSource() throws SQLException {
DynamicDataSource dynmicDataSource = new DynamicDataSource();
Map
5、编写DynamicDataSource.java
package com.example.demo.common.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
*
* @ClassName: DynamicDataSource
* @Description: TODO(根据Key切换数据源)
* @author willdas
* @date 2018年9月12日 下午5:21:10
*
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
/*
* 根据Key返回targetDataSources
*/
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSource();
}
}
6、编写DynamicDataSourceHolder.java
package com.example.demo.common.config;
import java.util.ArrayList;
import java.util.List;
/**
*
* @ClassName: DynamicDataSourceHolder
* @Description: TODO(存放数据源对应的key)
* @author willdas
* @date 2018年9月12日 下午5:50:00
*
*/
public class DynamicDataSourceHolder {
/*
* 线程本地环境
*/
private static final ThreadLocal contextHolders = new ThreadLocal();
/*
* 数据源列表
*/
public static List dataSourceIds = new ArrayList();
/*
* 设置数据源
*/
public static void setDataSource(String customerType) {
contextHolders.set(customerType);
}
/*
* 获取数据源
*/
public static String getDataSource() {
return (String) contextHolders.get();
}
/*
* 清除数据源
*/
public static void clearDataSource() {
contextHolders.remove();
}
/*
* 判断指定DataSrouce当前是否存在
*/
public static boolean containsDataSource(String dataSourceId) {
return dataSourceIds.contains(dataSourceId);
}
}
7、编写TargetDataSource.java
package com.example.demo.common.config;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @ClassName: TargetDataSource
* @Description: TODO(自定义切换数据源)
* @author willdas
* @date 2018年9月12日 上午9:29:44
*
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
String dataSource();
}
8、修改StudentServiceImpl.java,在修改方法加上注解切换到数据源2上
/**
* 修改学生信息 (修改的是数据源2的数据)
*/
@TargetDataSource(dataSource = "twoDataSource")
@Override
public int updateByPrimaryKey(Student stu) {
return studentMapper.updateByPrimaryKey(stu);
}
9、修改DemoApplication.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement //开启事务支持
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
10、整体项目目录如下:
11、先Maven clean,然后Maven install,最后右键DemoApplication.java,Run As 启动程序
12、打开Postman,开始测试
(1)先看下数据库数据
数据库1的数据
数据库2的数据
(2)测试查询(查出来的是数据库1的数据):
(3)测试修改功能(数据库2中id为5的数据被修改了):
至此SpringBoot使用AOP完成多数据源切换功能完成。感谢阅读。共同进步