一、springboot项目的基本搭建
相信大家都熟悉,不需要我多说,这里我用的是idea开发工具。
二、基本的配置
我的项目目录具体如下:
1.一个项目最重要的是pom.xml文件,其中的依赖起着至关重要的作用,所以我们首先必须明白我们项目需要哪些依赖,这里我把我需要的依赖展示出来,供大家参考:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wwd.frank</groupId> <artifactId>sunny-starter-core</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot_mybatisplus</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!--<dependency>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-jdbc</artifactId>--> <!--</dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--添加jsp依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!-- SpringBoot - MyBatis 逆向工程 --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> <!-- MyBatis 通用 Mapper --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>1.1.4</version> </dependency> <!--新加的开始--> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.6</version> </dependency> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.7.0</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.2</version> </dependency> <dependency> <groupId>com.vaadin.external.google</groupId> <artifactId>android-json</artifactId> <version>0.0.20131108.vaadin1</version> <scope>compile</scope> </dependency> <!-- https://mvnrepository.com/artifact/net.sourceforge.jexcelapi/jxl --> <dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifactId>jxl</artifactId> <version>2.6.12</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.9</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2.1-b03</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-cli</artifactId> <version>0.5.0.M5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <!--部署热启动依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <!--将resources目录下的配置文件编译进classes文件 --> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <configurationFile>src/main/resources/generatorConfig.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> <executions> <execution> <id>Generate MyBatis Artifacts</id> <goals> <goal>generate</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>3.5.0</version> </dependency> </dependencies> </plugin> </plugins> </build> </project>
2.application.properties为项目的基本配置文件,包含数据源的配置和端口配置,还有其他一些参数配置等,具体如下:
server.port=8088 #spring.datasource.url=jdbc:mysql://localhost:3306/bamsdb?useUnicode=true&characterEncoding=utf-8&useSSL=false #spring.datasource.url=jdbc:mysql://localhost:3306/bamsdb?characterEncoding=utf-8&useSSL=false #spring.datasource.username=bams #spring.datasource.password=Bams@123 #spring.datasource.driver-class-name=com.mysql.jdbc.Driver #spring.datasource.hikari.login-timeout=1000 #spring.datasource.hikari.maximum-pool-size=30 #数据源one spring.datasource.one.name=oneDatasource spring.datasource.one.jdbc-url=jdbc:mysql://localhost:3306/bamsdb?characterEncoding=utf-8&useSSL=false spring.datasource.one.username=bams spring.datasource.one.password=Bams@123 spring.datasource.one.driver-class-name=com.mysql.jdbc.Driver spring.datasource.one.hikari.login-timeout=1000 spring.datasource.one.hikari.maximum-pool-size=30 #数据源two spring.datasource.two.name=twoDatasource spring.datasource.two.jdbc-url=jdbc:mysql://localhost:3306/bamsdb?characterEncoding=utf-8&useSSL=false spring.datasource.two.username=bams spring.datasource.two.password=Bams@123 spring.datasource.two.driver-class-name=com.mysql.jdbc.Driver spring.datasource.two.hikari.login-timeout=1000 spring.datasource.two.hikari.maximum-pool-size=30 mybatis.mapper-locations=classpath:com/wwd/frank/dao/mapper/*.xml
被注释的是单数据源配置,下面的两个配置one、two为多数据源配置。
3.generatorConfig.xml为数据库反向生成的配置文件,可以生成dao层、entity层、service层和mapper.xml层,具体配置内容为:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!--mysql 连接数据库jar 这里选择自己本地位置--> <classPathEntry location="C:\Users\john\.m2\repository\mysql\mysql-connector-java\5.1.30\mysql-connector-java-5.1.30.jar" /> <context id="testTables" targetRuntime="MyBatis3"> <!-- 实现序列化 --> <plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin> <commentGenerator> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="false" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/bamsdb" userId="bams" password="Bams@123"> </jdbcConnection> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true 时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- 生成的路径及名称 --> <!-- 生成模型(PO)的包名和位置 --> <javaModelGenerator targetPackage="com.wwd.frank.entity" targetProject="src/main/java"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- 生成映射文件的包名和位置--> <sqlMapGenerator targetPackage="com.wwd.frank.dao.mapper" targetProject="src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- 生成DAO的包名和位置--> <javaClientGenerator type="XMLMAPPER" targetPackage="com.wwd.frank.dao" targetProject="src/main/java"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 列出要生成代码的所有表,这里配置的是不生成Example文件 只需要改tableName(表名)和 domainObjectName(实体名)--> <table tableName="fap_user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context> </generatorConfiguration>
这里需要我们改对应的mysql-connector-java-5.1.30.jar地址、数据源参数、生成文件路径及数据源表名等。
启动项目后,在项目的右边栏中找到maven_projects菜单,点击进去找到Plugin下的mybatis-generator,然后双击mybatis-generator:generate,如果程序不报错,并且有生成的dao层包、.xml文件、entity包及对应的实体,说明反向生成建模成功,我们的配置没问题。
4.线程池的配置
4.1首先我们要知道有哪些线程池:
a.newCachedThreadPool,是一种线程数量不定的线程池,并且其最大线程数为Integer.MAX_VALUE,这个数是很大的,一个可缓存线程池,如果线程池长度 超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。但是线程池中的空闲线程都有超时限制,这个超时时长是60秒,超过60秒闲置线程就会被 回收。调用execute将重用以前构造的线程(如果线程可用)。这类线程池比较适合执行大量的耗时较少的任务,当整个线程池都处于闲置状态时,线程池中的 线程都会超时被停止。
b.newFixedThreadPool 创建一个指定工作线程数量的线程池,每当提交一个任务就创建一个工作线程,当线程 处于空闲状态时,它们并不会被回收,除非线 程池被关闭了,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列(没有大小限制)中。由于newFixedThreadPool只有核心线程 并且这些核心线程不会被回收,这样它更加快速底相应外界的请求。
c.newScheduledThreadPool 创建一个线程池,它的核心线程数量是固定的,而非核心线程数是没有限制的,并且当非核心线程闲置时会被立即回收,它可安 排给定延迟后运行命令或者定期地执行。这类线程池主要用于执行定时任务和具有固定周期的重复任务。
d.newSingleThreadExecutor这类线程池内部只有一个核心线程,以*队列方式来执行该线程,这使得这些任务之间不需要处理线程同步的问题,它确保所 有的任务都在同一个线程中按顺序中执行,并且可以在任意给定的时间不会有多个线程是活动的。
4.2 在这里,我们使用newCachedThreadPool来创建线程池,在目录文件configs下的TaskPoolConfig类中配置,如下:
TaskPoolConfig.java的具体代码如下:
package com.wwd.frank.configs; import org.apache.tomcat.util.threads.ThreadPoolExecutor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; /** * 线程池配置类 */ @EnableAsync @Configuration public class TaskPoolConfig { private int corePoolSize = 10;//线程池维护线程的最少数量 private int maxPoolSize = 100;//线程池维护线程的最大数量 private int queueCapacity = 8; //缓存队列 private int keepAlive = 60;//允许的空闲时间 private int waitAlive = 60;//允许的等待时间 @Bean("taskExecutor") public Executor myExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); //线程名前缀 executor.setThreadNamePrefix("taskExecutor-"); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //对拒绝task的处理策略 executor.setKeepAliveSeconds(keepAlive); executor.setAwaitTerminationSeconds(waitAlive); executor.initialize(); return executor; } }
线程池配置完成,下面需要我们使用了。
4.3 定时任务执行引用线程池,文件所在目录,如下:
我们在Task文件下创建Task.java类,在类里创建我几个方法,每个方法都利用了线程池的操作,在PoolTask.java类中定义定时任务,执行操作,代码如下:
Task.java类的代码:
package com.wwd.frank.task.poolTask; import com.wwd.frank.entity.User; import groovy.util.logging.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.util.List; import java.util.Random; /** * * 利用线程池做定时任务 */ @Slf4j @Component public class Task { private final Logger logger = LoggerFactory.getLogger(getClass()); public static Random random = new Random(); @Autowired private com.wwd.frank.dao.mapper.UserMapper usermapper; @Async("taskExecutor") public void doTaskOne() throws Exception { logger.info("doTaskOne ********* 开始做任务一,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); List<User> list = usermapper.findAll(); logger.info("************************查询到的数据为:"+list.toString()); logger.info("doTaskOne ********* 完成任务一,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskTwo() throws Exception { logger.info("doTaskTwo ********* 开始做任务二,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskTwo ********* 完成任务二,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskThree() throws Exception { logger.info("doTaskThree ********* 开始做任务三,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskThree ********* 完成任务三,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskFour() throws Exception { logger.info("doTaskFour ********* 开始做任务四,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskFour ********* 完成任务四,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskFive() throws Exception { logger.info("doTaskFive ********* 开始做任务五,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskFive ********* 完成任务五,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskSix() throws Exception { logger.info("doTaskSix ********* 开始做任务六,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskSix ********* 完成任务六,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskSeven() throws Exception { logger.info("doTaskSeven ********* 开始做任务七,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskSeven ********* 完成任务七,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskEight() throws Exception { logger.info("doTaskEight ********* 开始做任务八,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskEight ********* 完成任务八,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskNine() throws Exception { logger.info("doTaskNine ********* 开始做任务九,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskNine ********* 完成任务九,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } @Async("taskExecutor") public void doTaskTen() throws Exception { logger.info("doTaskTen ********* 开始做任务十,线程名为:"+ Thread.currentThread().getName()); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); logger.info("doTaskTen ********* 完成任务十,耗时:" + (end - start) + "毫秒,线程名为:"+ Thread.currentThread().getName()); } }
PoolTask.java类的代码:
package com.wwd.frank.task.poolTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * 利用线程池执行异步定时任务 */ @Component public class PoolTask { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private Task task; /** * 每隔一秒执行一次 */ @Scheduled(fixedRate =5000) public void logTime() throws Exception { logger.info("**********************线程池的定时任务开始执行**********************"); task.doTaskOne(); task.doTaskTwo(); task.doTaskThree(); task.doTaskFour(); task.doTaskFive(); task.doTaskSix(); task.doTaskSeven(); task.doTaskEight(); task.doTaskNine(); task.doTaskTen(); //在多线程编程中,Thread.CurrentThread 表示获取当前正在运行的线程,join方法是阻塞当前调用线程,直到某线程完全执行才调用线程继续执行, //如果获取的当前线程是主线程,调用Join方法,当前的线程会阻塞住,因为线程无法结束 // Thread.currentThread().join(); } }
特别注意的是,不建议使用Thread.currentThread().join(),因为可能会引起线程阻塞的情况发生。
5.多数据源的配置使用
你应该注意到,在开始的时候,application.properties中有多个数据源的配置,就是在项目中引用多数据源,满足我们项目的多数据库的操作。
首先,在application.properties中配置我们需要到的数据库参数,具体如下:
server.port=8088 #数据源one spring.datasource.one.name=oneDatasource spring.datasource.one.jdbc-url=jdbc:mysql://localhost:3306/bamsdb?characterEncoding=utf-8&useSSL=false spring.datasource.one.username=bams spring.datasource.one.password=Bams@123 spring.datasource.one.driver-class-name=com.mysql.jdbc.Driver spring.datasource.one.hikari.login-timeout=1000 spring.datasource.one.hikari.maximum-pool-size=30 #数据源two spring.datasource.two.name=twoDatasource spring.datasource.two.jdbc-url=jdbc:mysql://localhost:3306/bamsdb?characterEncoding=utf-8&useSSL=false spring.datasource.two.username=bams spring.datasource.two.password=Bams@123 spring.datasource.two.driver-class-name=com.mysql.jdbc.Driver spring.datasource.two.hikari.login-timeout=1000 spring.datasource.two.hikari.maximum-pool-size=30 mybatis.mapper-locations=classpath:com/wwd/frank/dao/mapper/*.xml
配置中的参数名字必须对应上,版本不一致,参数名可能匹配不上,所以要特别注意了。
然后,在文件包moreDataResources下创建两个对应的数据源配置类,目录如下:
DataResourceOne.java类中配置数据源one,DataResourceTwo.java配置数据源two,具体如下:
DataResourceOne.java类的代码:
package com.wwd.frank.moreDataResources; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /** * 数据源one */ @Configuration @MapperScan(basePackages = "com.wwd.frank.dao.mapper", sqlSessionTemplateRef = "oneSqlSessionTemplate") public class DataResourceOne { /** * 配置数据数据源 master * * @return */ @Bean(name = "oneDatasource") @ConfigurationProperties(prefix = "spring.datasource.one") @Primary public DataSource masterDatasource() { return DataSourceBuilder.create().build(); } /** * 配置session工厂 * * @param dataSource * @return * @throws Exception */ @Bean(name = "oneSqlSessionFactory") @Primary public SqlSessionFactory masterSqlSessionFactory(@Qualifier("oneDatasource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); // bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:")); return bean.getObject(); } /** * 配置事务管理器 * * @param dataSource * @return */ @Bean(name = "oneTransactionManger") @Primary public DataSourceTransactionManager masterTransactionManger(@Qualifier("oneDatasource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } /** * 模版 * * @param sqlSessionFactory * @return * @throws Exception */ @Bean(name = "oneSqlSessionTemplate") @Primary public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("oneSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
DataResourceTwo.java类的代码:
package com.wwd.frank.moreDataResources; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /** * 数据源two */ @Configuration @MapperScan(basePackages = "com.wwd.frank.dao.mapperTwo" ,sqlSessionTemplateRef = "twoSqlSessionTemplate") public class DataResourceTwo { /** * 配置数据数据源 slave * @return */ @Bean(name = "twoDatasource") @ConfigurationProperties(prefix = "spring.datasource.two") // @Primary public DataSource slaveDatasource(){ return DataSourceBuilder.create().build(); } /** * 配置session工厂 * @param dataSource * @return * @throws Exception */ @Bean(name = "twoSqlSessionFactory") // @Primary public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("twoDatasource") DataSource dataSource) throws Exception{ SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); // bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:")); return bean.getObject(); } /** * 配置事务管理器 * @param dataSource * @return */ @Bean(name = "twoTransactionManger") // @Primary public DataSourceTransactionManager slaveTransactionManger(@Qualifier("twoDatasource") DataSource dataSource){ return new DataSourceTransactionManager(dataSource); } /** * 模版 * @param sqlSessionFactory * @return * @throws Exception */ @Bean(name = "twoSqlSessionTemplate") // @Primary public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("twoSqlSessionFactory")SqlSessionFactory sqlSessionFactory) throws Exception{ return new SqlSessionTemplate(sqlSessionFactory); } }
对应的两个配置类中,注解@MapperScan(basePackages = "com.wwd.frank.dao.mapperTwo" ,sqlSessionTemplateRef = "twoSqlSessionTemplate")
需要特别注意,basePackages 包路径是对应的Mapper.xml文件路径,每种数据源对应一个Mapper.xml文件,在我们使用时,在server实现层中只需要引用我们想用的数据库对应的Mapper.java接口类就可以达到需求,这里不需要对其实现,我们的项目是默认允许自动生成实现类。
配置完成后,我们只需要在server的实现类中注入Mapper.java接口类就可以了。
以User为例,UserServiceImp.java实现类中如何引用不同的数据源的代码如下:
package com.wwd.frank.service.imp; import com.wwd.frank.entity.User; import com.wwd.frank.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceImp implements UserService { @Autowired private com.wwd.frank.dao.mapper.UserMapper userMapper; @Autowired private com.wwd.frank.dao.mapperTwo.UserMapperTwo userMapperTwo; @Override public List<User> findAll() { return userMapper.findAll(); } @Override public List<User> findTestAll() { return userMapperTwo.findAllTwo(); } @Override public int insertSelective(User record) { return userMapper.insert(record); } }
我们这时的多数据源配置就完成了,只需要我们测试配置是否正确,我自己测试没问题的,希望能给你们带来帮助!