最近在研究Spring Cloud搭建微服务相关,对于一个庞大的系统,需要拆分为多个微服务,每个服务相当于一个模块,负责不同的事情,各司其职,当然,数据库之间也需要保持相对独立,这样就需要涉及到多个数据库,那么,如何使用Spring Boot配置多数据源呢?
首先,我们需要一个自定义注解,命名为:DataSource
@Retention(RetentionPolicy.RUNTIME)//将该注解定义在运行时级别@Target(ElementType.METHOD)//将该注解应用于方法上public @interface DataSource { String value() default "user";}然后创建数据源的类: DynamicDataSourceHolder
public class DynamicDataSourceHolder { /** * 默认数据源 * */ public static final String DEFAULT_DATASOURCE = "user"; public static final ThreadLocal<String> holder = new ThreadLocal<String>(); public static void setDataSource(String name) { holder.set(name); } public static String getDataSouce() { return holder.get(); } public static void clearDataSouce() { holder.remove(); } } 配置动态数据源的类: DynamicDataSource
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceHolder.getDataSouce(); } } 然后我们生成数据源,创建 MybatisConfig类
@Configuration@PropertySource("classpath:jdbc.properties") //引入配置文件jdbc.properties中的信息
@MapperScan(basePackages ={"com.drive.dbuser.dao"} , sqlSessionFactoryRef = "sqlSessionFactory") // 配置Mapper作用的位置public class MybatisConfig { @Bean(name = "user") @ConfigurationProperties(prefix = "user") public DataSource dataSourceUser(){ return DataSourceBuilder.create().build(); } //生成user数据源 @Bean(name = "drive") @ConfigurationProperties(prefix = "drive") public DataSource dataSourceDrive(){ return DataSourceBuilder.create().build(); } //生成drive数据源
@Bean(name = "order") @ConfigurationProperties(prefix = "order") public DataSource dataSourceOrder(){ return DataSourceBuilder.create().build(); } //生成order数据源 @Bean(name = "dynamicDataSource") public DataSource dataSource(){ DynamicDataSource dynamicDataSource = new DynamicDataSource(); // 默认数据源---User dynamicDataSource.setDefaultTargetDataSource(dataSourceUser()); // 配置多数据源 Map<Object, Object> dataSourceMap = new HashMap(5); dataSourceMap.put("user", dataSourceUser()); dataSourceMap.put("drive", dataSourceDrive()); dataSourceMap.put("order", dataSourceOrder()); dynamicDataSource.setTargetDataSources(dataSourceMap); return dynamicDataSource; } //配置多数据源 @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource()); // //添加XML目录 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); try { factoryBean.setMapperLocations(resolver.getResources("classpath*:com/drive/dbuser/mapper/*.xml")); //生效的位置 return factoryBean.getObject(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } }//创建Session工厂/* @Bean public SqlSessionTemplate sqlSessionTemplate() throws Exception { //SqlSessionTemplate 是 MyBatis-Spring 的核心。 这个类负责管理 MyBatis 的 SqlSession, 调用 MyBatis 的 SQL 方法 SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory()); // 使用上面配置的Factory return template; }*/} 我们来看一下 jdbc.properties的配置文件的信息:
#用户服务库user.url=jdbc:mysql:***user.username=***user.password=***#打车服务库drive.url=drive.username=drive.password=#订单服务库order.url=order.username=order.password=1 user.driverClassName=com.mysql.jdbc.Driverdrive.driverClassName=com.mysql.jdbc.Driverorder.driverClassName=com.mysql.jdbc.Driver
这样我们的多数据源都配置好了,那么如何调用呢,比如说我需要先去user数据库里查数据,然后再去drive数据库里添加数据,这样怎么动态的更换数据源呢?我们可以使用Spring 中的一大核心AOP,首先我们需要在application.properties文件中开启AOP
spring.aop.auto=true#开启AOP 然后创建 DataSourceAspect类,
@Aspect@Componentpublic class DataSourceAspect { @Pointcut("execution(* com.drive.dbuser.dao.*.*(..))") public void declareJointPointExpression() { } @Before("declareJointPointExpression()") public void beforeSwitchDS(JoinPoint point){ //获得当前访问的class Class<?>[] className = point.getTarget().getClass().getInterfaces(); //获得访问的方法名 String methodName = point.getSignature().getName(); //得到方法的参数的类型 Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes(); String dataSource = DynamicDataSourceHolder.DEFAULT_DATASOURCE; try { // 得到访问的方法对象 Method method = className[0].getMethod(methodName, argClass); // 判断是否存在@DataSource注解 if (method.isAnnotationPresent(DataSource.class)) { DataSource annotation = method.getAnnotation(DataSource.class); // 取出注解中的数据源名 dataSource = annotation.value(); } } catch (Exception e) { e.printStackTrace(); } // 切换数据源 DynamicDataSourceHolder.setDataSource(dataSource); } @After("declareJointPointExpression()") public void afterSwitchDS(JoinPoint point){ DynamicDataSourceHolder.clearDataSouce(); } } 这时,我们再看一下关于Dao层的内容:
@DataSource("user")List<CustomerVO> selectCustomer(CustomerVO customerVO);
我们创建一个切面类,当我们调用Dao层之前,会首先查看在Mapper 接口上方法上的注解,并将它作为数据源,注入到DynamicDataSourceHolder中,这样,就可以实现动态切换数据源了。 最后,我们在启动类上需要加上
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) //通过禁用指定的自动化配置来避免加载不必要的自动化配置@EnableConfigurationProperties //注解是用来开启对@ConfigurationProperties注解配置Bean的支持, 该注解告诉Spring Boot 使能支持@ConfigurationProperties:注解主要用来把properties配置文件转化为bean来使用
当然,不要忘了在pom.xml中配置所需要的依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency> <!-- Spring Boot Mybatis 依赖 --><dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version></dependency>
<!-- MySQL 连接驱动依赖 --><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.9</version></dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version></dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.12</version></dependency> <!--log4j--><dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version></dependency> 好了,大功告成了,喜欢的朋友们记得关注我一下!
原文地址:https://www.cnblogs.com/hello-world-exception/p/9008437.html
时间: 2024-09-29 03:39:51