使用springboot + druid + mybatisplus完成多数据源配置
Posted 快乐在角落里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用springboot + druid + mybatisplus完成多数据源配置相关的知识,希望对你有一定的参考价值。
一. 简介
1. 版本
springboot版本为2.0.3.RELEASE,mybatisplus版本为2.1.9, druid版本为1.1.9,swagger版本为2.7.0
2. 项目地址
https://gitee.com/wbsxch/ssm.git
该地址有初始sql和测试方法
3. 留个记录,方便查找
开发步骤:
1. 新建springboot项目。
2. 导入依赖 --> devtools,lombok,web,thymeleaf,mysql,aop,mybatisplus,druid,swagger。
3. maven多环境配置。
4. 编写application.yml --> 项目端口,项目路径名,mybatisplus配置,mysql多数据源配置。
5. 新建DataSourceContextHolder 用于设置,获取,清空 当前线程内的数据源变量。
6. 新建 MultipleDataSource 实现 AbstractRoutingDataSource 类。重写determineCurrentLookupKey(),通过
DataSourceContextHolder 获取数据源变量,用于当作lookupKey取出指定的数据源。
7. 新建DataSourceEnum 用于存放数据源名称。
8. 新建注解 DataSource,用于aop类中当作切入点来选择数据源。
编写aop类 --> DataSourceAspect.java
9. 新建并配置DruidConfiguration,MybatisplusConfiguration,SwaggerConfiguration 三个类。
DruidConfiguration --> StatViewServlet 和 WebStatFilter Druid监控配置和监控过滤器。
MybatisplusConfiguration --> mybatisplus 分页插件,SQL执行效率插件
数据源Bean,MultipleDataSource 注入
SqlSessionFactory注入
SwaggerConfiguration --> 常规配置。
10. crud Controller接口。
11. 完整项目结构
二. 详细步骤
1. 新建springboot项目
idea新建Empty项目 然后创建springboot项目 勾选 devtools,lombok,web,thymeleaf,mysql
2. 导入依赖
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.seawaterbt</groupId> <artifactId>ssm</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>ssm</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <druid.version>1.1.9</druid.version> <swagger.version>2.7.0</swagger.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>2.1.9</version> </dependency> <!-- druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies> <profiles> <profile> <id>prod</id> <properties> <config.dir>prod</config.dir> </properties> </profile> <profile> <id>dev</id> <properties> <config.dir>dev</config.dir> </properties> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>qa</id> <properties> <config.dir>qa</config.dir> </properties> </profile> </profiles> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <resources> <resource> <filtering>true</filtering> <directory>src/main/resources/config/${config.dir}</directory> <includes> <include>*.*</include> </includes> </resource> <resource> <directory>src/main/resources/</directory> </resource> </resources> </build> </project>
3. Maven多环境配置 看pom文件
4. 编写application.yml
application.yml
server: port: 8080 servlet: context-path: /ssm spring: datasource: druid: db1: username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///mds initialSize: 5 minIdle: 5 maxActive: 20 db2: username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///ssj initialSize: 5 minIdle: 5 maxActive: 20 mybatis-plus: # 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*Mapper.xml # 如果是放在resource目录 classpath:/mapper/*Mapper.xml mapper-locations: classpath:/mapper/*Mapper.xml #实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.seawatebt.ssm.entity global-config: #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; id-type: 0 #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" field-strategy: 2 #驼峰下划线转换 db-column-underline: true #mp2.3+ 全局表前缀 mp_ #table-prefix: mp_ #刷新mapper 调试神器 refresh-mapper: true #数据库大写下划线转换 #capital-mode: true #逻辑删除配置(下面3个配置) logic-delete-value: 4 logic-not-delete-value: 0 configuration: #配置返回数据库(column下划线命名&&返回java实体是驼峰命名),自动匹配无需as(没开启这个,SQL需要写as: select user_id as userId) map-underscore-to-camel-case: true cache-enabled: false #配置JdbcTypeForNull, oracle数据库必须配置 jdbc-type-for-null: \'null\'
5. 新建DataSourceContextHolder
DataSourceContextHolder.java
package com.seawaterbt.ssm.multiple; public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new InheritableThreadLocal<>(); /** * 设置数据源 * @param db */ public static void setDataSource(String db){ contextHolder.set(db); } /** * 取得当前数据源 * @return */ public static String getDataSource(){ return contextHolder.get(); } /** * 清除上下文数据 */ public static void clear(){ contextHolder.remove(); } }
6. 新建 MultipleDataSource
MultipleDataSource.java
package com.seawaterbt.ssm.multiple; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class MultipleDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } }
7. 新建DataSourceEnum
DataSourceEnum.java
package com.seawaterbt.ssm.enums; public enum DataSourceEnum { DB1("db1"),DB2("db2"); private String value; DataSourceEnum(String value){this.value=value;} public String getValue() { return value; } }
8. 新建注解 DataSource
DataSource.java
package com.seawaterbt.ssm.annotation; import com.seawaterbt.ssm.enums.DataSourceEnum; import java.lang.annotation.*; @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { DataSourceEnum value() default DataSourceEnum.DB1; }
DataSourceAspect.java
@Component @Slf4j @Aspect @Order(-1) public class DataSourceAspect { @Pointcut("@within(com.seawaterbt.ssm.annotation.DataSource) || @annotation(com.seawaterbt.ssm.annotation.DataSource)") public void pointCut(){ } @Before("pointCut() && @annotation(dataSource)") public void doBefore(DataSource dataSource){ log.info("选择数据源---"+dataSource.value().getValue()); DataSourceContextHolder.setDataSource(dataSource.value().getValue()); } @After("pointCut()") public void doAfter(){ DataSourceContextHolder.clear(); } }
9. 新建并配置DruidConfiguration,MybatisplusConfiguration,SwaggerConfiguration
DruidConfiguration.java
package com.seawaterbt.ssm.config; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; 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; @Configuration public class DruidConfiguration { @Bean public ServletRegistrationBean startViewServlet(){ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*"); // IP白名单 servletRegistrationBean.addInitParameter("allow","127.0.0.1"); // IP黑名单(共同存在时,deny优先于allow) servletRegistrationBean.addInitParameter("deny","127.0.0.1"); //控制台管理用户 servletRegistrationBean.addInitParameter("loginUsername","admin"); servletRegistrationBean.addInitParameter("loginPassword","123456"); //是否能够重置数据 servletRegistrationBean.addInitParameter("resetEnable","false"); return servletRegistrationBean; } @Bean public FilterRegistrationBean statFilter(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter()); //添加过滤规则 filterRegistrationBean.addUrlPatterns("/*"); //忽略过滤的格式 filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return filterRegistrationBean; } }
MyBatiesPlusConfiguration.java
package com.seawaterbt.ssm.config; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; import com.baomidou.mybatisplus.MybatisConfiguration; import com.baomidou.mybatisplus.entity.GlobalConfiguration; import com.baomidou.mybatisplus.mapper.LogicSqlInjector; import com.baomidou.mybatisplus.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.plugins.PerformanceInterceptor; import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean; import com.seawaterbt.ssm.enums.DataSourceEnum; import com.seawaterbt.ssm.multiple.MultipleDataSource; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.type.JdbcType; import org.mybatis.spring.annotation.MapperScan; 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.context.annotation.Profile; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; @Configuration @MapperScan("com.seawaterbt.ssm.mapper*") public class MyBatiesPlusConfiguration { /* * 分页插件,自动识别数据库类型 * 多租户,请参考官网【插件扩展】 */ @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 开启 PageHelper 的支持 paginationInterceptor.setLocalPage(true); return paginationInterceptor; } /** * SQL执行效率插件 */ @Bean @Profile({"dev","qa"})// 设置 dev test 环境开启 public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); performanceInterceptor.setMaxTime(1000); performanceInterceptor.setFormat(true); return performanceInterceptor; } @Bean(name = "db1") @ConfigurationProperties(prefix = "spring.datasource.druid.db1" ) public DataSource db1() { return DruidDataSourceBuilder.create().build(); } @Bean(name = "db2") @ConfigurationProperties(prefix = "spring.datasource.druid.db2" ) public DataSource db2() { return DruidDataSourceBuilder.create().build(); } /** * 动态数据源配置 * @return */ @Bean @Primary public DataSource multipleDataSource(@Qualifier("db1") DataSource db1, @Qualifier("db2") DataSource db2) { MultipleDataSource multipleDataSource = new MultipleDataSource(); Map< Object, Object > targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceEnum.DB1.getValue(), db1); targetDataSources.put(DataSourceEnum.DB2.getValue(), db2); //添加数据源 multipleDataSource.setTargetDataSources(targetDataSources); //设置默认数据源 multipleDataSource.setDefaultTargetDataSource(db1); return multipleDataSource; } @Bean("sqlSessionFactory") public SqlSessionFactory sqlSessionFactory() throws Exception { MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean(); sqlSessionFactory.setDataSource(multipleDataSource(db1(),db2())); //sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/*/*Mapper.xml")); MybatisConfiguration configuration = new MybatisConfiguration(); //configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class); configuration.setJdbcTypeForNull(JdbcType.NULL); configuration.setMapUnderscoreToCamelCase(true); configuration.setCacheEnabled(false); sqlSessionFactory.setConfiguration(configuration); sqlSessionFactory.setPlugins(new Interceptor[]{ //PerformanceInterceptor(),OptimisticLockerInterceptor() paginationInterceptor() //添加分页功能 }); //sqlSessionFactory.setGlobalConfig(globalConfiguration()); return sqlSessionFactory.getObject(); } /*@Bean public GlobalConfiguration globalConfiguration() { GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector()); conf.setLogicDeleteValue("-1"); conf.setLogicNotDeleteValue("1"); conf.setIdType(0); //conf.setMetaObjectHandler(new MyMetaObjectHandler()); conf.setDbColumnUnderline(true); conf.setRefresh(true); return conf; }*/ }
SwaggerConfiguration.java
package com.seawaterbt.ssm.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class SwaggerConfiguration { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.seawaterbt.ssm.controller")) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo(){ return new ApiInfoBuilder() .title("多数据源 SSM 测试服务") .description("多数据源 SSM 测试文档") .termsOfServiceUrl("http://www.seawaterbt.com") //.contact(new Contact("海水不甜","http://www.seawaterbt.com","809318068@qq.com")) .version("1.0") .build(); } }
10. crud Controller接口
1. Entity
Student.java
package com.seawaterbt.ssm.entity; import com.baomidou.mybatisplus.annotations.TableId; import com.baomidou.mybatisplus.annotations.TableName; import com.baomidou.mybatisplus.enums.IdType; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Api("学生实体对象") @Data @TableName("t_student") public class Student { @ApiModelProperty("学生id") @TableId(type = IdType.AUTO) private Integer id; @ApiModelProperty("学生姓名") private String name; @ApiModelProperty("学生年龄") private Integer age; @ApiModelProperty("学生班级") private String classname; }
Teacher.java
package com.seawaterbt.ssm.entity; import com.baomidou.mybatisplus.annotations.TableId; import com.baomidou.mybatisplus.annotations.TableName; import com.baomidou.mybatisplus.enums.IdType; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Api("老师实体对象") @Data @TableName("t_teacher") public class Teacher { @ApiModelProperty("老师id") @TableId(type = IdType.AUTO) private Integer id; @ApiModelProperty("老师姓名") private String name; @ApiModelProperty("老师年龄") private Integer age; @ApiModelProperty("老师所教学科") private String subject; }
2. Mapper 接口及其xml
StudentMapper.java
package com.seawaterbt.ssm.mapper; import com.baomidou.mybatisplus.mapper.BaseMapper; import com.seawaterbt.ssm.entity.Student; public interface StudentMapper extends BaseMapper<Student> { }
StudentMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.seawaterbt.ssm.mapper.StudentMapper"> </mapper>
TeacherMapper.java
package com.seawaterbt.ssm.mapper; import com.baomidou.mybatisplus.mapper.BaseMapper; import com.seawaterbt.ssm.entity.Teacher; public interface TeacherMapper extends BaseMapper<Teacher> { }
TeacherMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.seawaterbt.ssm.mapper.TeacherMapper"> </mapper>
3. Service 接口及其实现类
StudentService.java
package com.seawaterbt.ssm.service; import com.baomidou.mybatisplus.service.IService; import com.seawaterbt.ssm.entity.Student; public interface StudentService extends IService<Student> { }
StudentServiceImpl.java
package com.seawaterbt.ssm.service.impl; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.seawaterbt.ssm.entity.Student; import com.seawaterbt.ssm.mapper.StudentMapper; import com.seawaterbt.ssm.service.StudentService; import org.springframework.stereotype.Service; @Service public class StudentServiceImpl extends ServiceImpl<StudentMapper,Student> implements StudentService { }
TeacherService.java
package com.seawaterbt.ssm.service; import com.baomidou.mybatisplus.service.IService; import com.seawaterbt.ssm.entity.Teacher; public interface TeacherService extends IService<Teacher> { }
TeacherServiceImpl.java
package com.seawaterbt.ssm.service.impl; import com.baomidou.mybatisplus.mapper.Wrapper; import com.baomidou.mybatisplus.plugins.Page; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.seawaterbt.ssm.annotation.DataSource; import com.seawaterbt.ssm.entity.Teacher; import com.seawaterbt.ssm.enums.DataSourceEnum; import com.seawaterbt.ssm.mapper.TeacherMapper; import com.seawaterbt.ssm.service.TeacherService; import org.springframework.stereotype.Service; import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; @Service public class TeacherServiceImpl extends ServiceImpl<TeacherMapper,Teacher> implements TeacherService { @Override @DataSource(DataSourceEnum.DB2) public boolean insert(Teacher entity) { return super.insert(entity); } @Override @DataSource(DataSourceEnum.DB2) public boolean deleteById(Serializable id) { return super.deleteById(id); } @Override @DataSource(DataSourceEnum.DB2) public boolean updateById(Teacher entity) { return super.updateById(entity); } @Override @DataSource(DataSourceEnum.DB2) public Teacher selectById(Serializable id) { return super.selectById(id); } @Override @DataSource(DataSourceEnum.DB2) public List<Teacher> selectList(Wrapper<Teacher> wrapper) { return super.selectList(wrapper); } @Override @DataSource(DataSourceEnum.DB2) public Page<Teacher> selectPage(Page<Teacher> page) { return super.selectPage(page); } @Override @DataSource(DataSourceEnum.DB2) public Page<Teacher> selectPage(Page<Teacher> page, Wrapper<Teacher> wrapper) { return super.selectPage(page, wrapper); } }
4. Vo
StudentVo.java
package com.seawaterbt.ssm.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("学生vo") public class StudentVo { @ApiModelProperty("学生姓名") private String name; @ApiModelProperty("学生年龄") private Integer age; @ApiModelProperty("学生班级") private String classname; }
TeacherVo.java
package com.seawaterbt.ssm.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("老师vo") public class TeacherVo { @ApiModelProperty("老师姓名") privateSpringBoot--使用Druid(德鲁伊)数据源SpringBoot:spring boot使用Druid和监控配置