• springBoot配置多数据源


    通过在mapper接口上添加自定数据源注解@DataSource来制定数据源

    1.添加切面aspectjweaver依赖

    1. <dependency>
    2. <groupId>org.aspectj</groupId>
    3. <artifactId>aspectjweaver</artifactId>
    4. <version>1.9.7</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>org.springframework.boot</groupId>
    8. <artifactId>spring-boot-starter-aop</artifactId>
    9. <version>1.5.9.RELEASE</version>
    10. </dependency>

    2.启动类添加切面支持注解@EnableAspectJAutoProxy(proxyTargetClass = true)

    @Import({DynamicDataSourceConfig.class})

    exclude = {DataSourceAutoConfiguration.class} 不加这个会报错,循环依赖问题(查了好久才解决)

    1. import org.linlinjava.litemall.db.datasources.DynamicDataSourceConfig;
    2. import org.mybatis.spring.annotation.MapperScan;
    3. import org.springframework.boot.SpringApplication;
    4. import org.springframework.boot.autoconfigure.SpringBootApplication;
    5. import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    6. import org.springframework.context.annotation.EnableAspectJAutoProxy;
    7. import org.springframework.context.annotation.Import;
    8. import org.springframework.scheduling.annotation.EnableScheduling;
    9. import org.springframework.transaction.annotation.EnableTransactionManagement;
    10. @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    11. @MapperScan("org.linlinjava.litemall.db.dao")
    12. @EnableTransactionManagement
    13. @EnableAspectJAutoProxy(proxyTargetClass = true)
    14. @EnableScheduling
    15. @Import({DynamicDataSourceConfig.class})
    16. public class Application {
    17. public static void main(String[] args) {
    18. SpringApplication.run(Application.class, args);
    19. }
    20. }

    3自定义注解DataSource.java

    1. import java.lang.annotation.*;
    2. /**
    3. * 多数据源注解
    4. *
    5. */
    6. @Target({ElementType.METHOD, ElementType.TYPE})
    7. @Retention(RetentionPolicy.RUNTIME)
    8. @Documented
    9. public @interface DataSource {
    10. String name() default "";
    11. }

    数据源名称枚举

    1. /**
    2. * 增加多数据源,在此配置
    3. *
    4. */
    5. public interface DataSourceNames {
    6. String LITEMALL = "mall";
    7. String ZOOM = "zoom";
    8. }

    动态数据源配置类

    1. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    2. import javax.sql.DataSource;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. /**
    6. * 动态数据源
    7. *
    8. */
    9. public class DynamicDataSource extends AbstractRoutingDataSource {
    10. private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    11. public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
    12. super.setDefaultTargetDataSource(defaultTargetDataSource);
    13. super.setTargetDataSources(new HashMap<>(targetDataSources));
    14. super.afterPropertiesSet();
    15. }
    16. @Override
    17. protected Object determineCurrentLookupKey() {
    18. return getDataSource();
    19. }
    20. public static void setDataSource(String dataSource) {
    21. contextHolder.set(dataSource);
    22. }
    23. public static String getDataSource() {
    24. return contextHolder.get();
    25. }
    26. public static void clearDataSource() {
    27. contextHolder.remove();
    28. }
    29. }

    配置多数据源

    1. import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
    2. import org.aspectj.lang.ProceedingJoinPoint;
    3. import org.aspectj.lang.annotation.Around;
    4. import org.aspectj.lang.annotation.Aspect;
    5. import org.aspectj.lang.annotation.Pointcut;
    6. import org.aspectj.lang.reflect.MethodSignature;
    7. import org.slf4j.Logger;
    8. import org.slf4j.LoggerFactory;
    9. import org.springframework.boot.context.properties.ConfigurationProperties;
    10. import org.springframework.context.annotation.Bean;
    11. import org.springframework.context.annotation.Configuration;
    12. import org.springframework.context.annotation.Primary;
    13. import org.springframework.core.Ordered;
    14. import org.springframework.stereotype.Component;
    15. import javax.sql.DataSource;
    16. import java.lang.reflect.Method;
    17. import java.util.HashMap;
    18. import java.util.Map;
    19. /**
    20. * 配置多数据源
    21. *
    22. */
    23. @Configuration
    24. public class DynamicDataSourceConfig {
    25. @Bean
    26. @ConfigurationProperties("spring.datasource.druid.mall")
    27. public DataSource liteMallDataSource() {
    28. return DruidDataSourceBuilder.create().build();
    29. }
    30. @Bean
    31. @ConfigurationProperties("spring.datasource.druid.zoom")
    32. public DataSource zoomDataSource() {
    33. return DruidDataSourceBuilder.create().build();
    34. }
    35. @Bean
    36. @Primary
    37. public DynamicDataSource dataSource(DataSource liteMallDataSource, DataSource zoomDataSource) {
    38. Map<String, DataSource> targetDataSources = new HashMap<>();
    39. targetDataSources.put(DataSourceNames.LITEMALL, liteMallDataSource);
    40. targetDataSources.put(DataSourceNames.ZOOM, zoomDataSource);
    41. return new DynamicDataSource(liteMallDataSource, targetDataSources);
    42. }
    43. @Aspect
    44. @Component
    45. class DataSourceAspect implements Ordered {
    46. protected Logger logger = LoggerFactory.getLogger(getClass());
    47. public DataSourceAspect() {
    48. System.out.println(0);
    49. }
    50. @Pointcut("@within(org.linlinjava.litemall.db.datasources.annotation.DataSource)")
    51. public void dataSourcePointCut() {
    52. System.out.println(0);
    53. }
    54. @Around("dataSourcePointCut()")
    55. public Object around(ProceedingJoinPoint point) throws Throwable {
    56. org.linlinjava.litemall.db.datasources.annotation.DataSource ds = null;
    57. Class clazz = point.getTarget().getClass();
    58. ds = (org.linlinjava.litemall.db.datasources.annotation.DataSource) clazz.getAnnotation(org.linlinjava.litemall.db.datasources.annotation.DataSource.class);
    59. if (ds == null) {
    60. MethodSignature signature = (MethodSignature) point.getSignature();
    61. Method method = signature.getMethod();
    62. ds = method.getAnnotation(org.linlinjava.litemall.db.datasources.annotation.DataSource.class);
    63. }
    64. if (ds == null) {
    65. DynamicDataSource.setDataSource(DataSourceNames.LITEMALL);
    66. logger.debug("set datasource is " + DataSourceNames.LITEMALL);
    67. } else {
    68. DynamicDataSource.setDataSource(ds.name());
    69. logger.debug("set datasource is " + ds.name());
    70. }
    71. try {
    72. return point.proceed();
    73. } finally {
    74. DynamicDataSource.clearDataSource();
    75. logger.debug("clean datasource");
    76. }
    77. }
    78. @Override
    79. public int getOrder() {
    80. return 1;
    81. }
    82. }
    83. }

    4.Yaml配置

    1. spring:
    2. datasource:
    3. type: com.alibaba.druid.pool.DruidDataSource
    4. druid:
    5. zoom: #数据源2
    6. url: xxxxxx/zoom?useUnicode=true&characterEncoding=utf8&useSSL=false
    7. driver-class-name: com.mysql.cj.jdbc.Driver
    8. username: 0000
    9. password: 00000
    10. filter:
    11. slf4j:
    12. enabled: true
    13. mall:
    14. url: jdbc:xxxxxx/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=false
    15. driver-class-name: com.mysql.cj.jdbc.Driver
    16. username: 00000
    17. password: 00000
    18. initial-size: 10
    19. max-active: 50
    20. min-idle: 10
    21. max-wait: 60000
    22. pool-prepared-statements: true
    23. max-pool-prepared-statement-per-connection-size: 20
    24. validation-query: SELECT 1 FROM DUAL
    25. test-on-borrow: false
    26. test-on-return: false
    27. test-while-idle: true
    28. time-between-eviction-runs-millis: 60000
    29. webStatFilter:
    30. enabled: true
    31. statViewServlet:
    32. enabled: false
    33. filter:
    34. stat:
    35. enabled: false

    5.测试

    1. import org.junit.Test;
    2. import org.junit.runner.RunWith;
    3. import org.linlinjava.litemall.db.dao.StatMapper;
    4. import org.linlinjava.litemall.db.dao.ZoomMapper;
    5. import org.linlinjava.litemall.db.datasources.DynamicDataSourceConfig;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    8. import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    9. import org.springframework.boot.test.context.SpringBootTest;
    10. import org.springframework.context.annotation.Import;
    11. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    12. import org.springframework.test.context.junit4.SpringRunner;
    13. import org.springframework.test.context.web.WebAppConfiguration;
    14. import javax.annotation.Resource;
    15. @WebAppConfiguration
    16. @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
    17. @RunWith(SpringRunner.class)
    18. @SpringBootTest
    19. @Import({DynamicDataSourceConfig.class})
    20. public class DbTest {
    21. @Autowired
    22. private ZoomMapper zoomMapper;
    23. @Test
    24. public void test() {
    25. System.out.println(zoomMapper.queryName());
    26. }
    27. }

    6,可能出现的异常

    ***************************
    APPLICATION FAILED TO START
    ***************************

    Description:

    The dependencies of some of the beans in the application context form a cycle:

    zoomMapperService (field org.linlinjava.litemall.db.dao.ZoomMapper org.linlinjava.litemall.db.dao.impl.ZoomMapperService.zoomMapper)

    zoomMapper defined in file [F:\workcode\litemall\litemall-db\target\classes\org\linlinjava\litemall\db\dao\ZoomMapper.class]

    sqlSessionFactory defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]
    ┌─────┐
    | dataSource defined in class path resource [org/linlinjava/litemall/db/datasources/DynamicDataSourceConfig.class]
    ↑ ↓
    | firstDataSource defined in class path resource [org/linlinjava/litemall/db/datasources/DynamicDataSourceConfig.class]
    ↑ ↓
    | org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker

    循环依赖问题

    2yaml配置问题

    Caused by: org.yaml.snakeyaml.parser.ParserException: while parsing a block mapping
     in 'reader', line 9, column 5:
            type: com.alibaba.druid.pool.Dru ... 
            ^
    expected <block end>, but found '<block mapping start>'
     in 'reader', line 19, column 7:
              mall:
              ^

        at org.yaml.snakeyaml.parser.ParserImpl$ParseBlockMappingKey.produce(ParserImpl.java:572)
        at org.yaml.snakeyaml.parser.ParserImpl.peekEvent(ParserImpl.java:158)
        at org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:148)
        at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:214)
        at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144)
        at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:236)
        at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:227)
        at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:215)
        at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144)
        at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:236)
        at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:227)
        at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:215)
        at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144)
        at org.yaml.snakeyaml.composer.Composer.getNode(Composer.java:85)
        at org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:123)
        at org.yaml.snakeyaml.Yaml$1.next(Yaml.java:547)
        at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:160)
        at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:134)
        at org.springframework.boot.env.OriginTrackedYamlLoader.load(OriginTrackedYamlLoader.java:75)
        at org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:50)
        at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.loadDocuments(ConfigFileApplicationListener.java:574)
        at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:528)
        ... 48 common frames omitted

  • 相关阅读:
    在vue-cli项目中打包的 dist 静态文件不能直接双击打开访问解决方法-直接打开访问是空白的解决方法
    机器学习 分类、回归、聚类、特征工程区别
    与git相关错误的究极解决方案
    Oracle 数据库的锁排查方法
    使用XShell、XFTP 连接 win7 虚拟机(windows、Linux无法远程登录问题)
    phpcms v9.任意文件上传漏洞复现
    用python解决这个问题
    人脸解锁设备时出现相机报错
    使用kubeadm方式搭建Kubernetes集群
    人脸识别9-FastDeploy人脸检测、识别、部署
  • 原文地址:https://blog.csdn.net/BIG_PEI/article/details/125487810