首页>>后端>>SpringBoot->SpringBoot多租户业务的多数据源动态切换解决方案

SpringBoot多租户业务的多数据源动态切换解决方案

时间:2023-11-29 本站 点击:0

数据源切换方法

Springboot提供了AbstractRoutingDataSource抽象类,类名意思是数据源路由,让用户可以选择根据需要切换当前数据源 该类提供了一个抽象方法determineCurrentLookupKey(), 切换数据源时springboot会调用这个方法,所以只需要实现该方法,在该方法中返回需要切换的数据源名称即可

源码解读

1.从类关系图中可以看出AbstractRoutingDataSource类实现的是DataSource接口(非最底层), 其要求实现一个方法getConnection(),即获取DB连接

2.AbstractRoutingDataSource实现了这两个方法

其中determineTargetDataSource()调用determineCurrentLookupKey()方法,取到当前设定的查找键,通过查找键在上下文this.resolvedDataSources属性中尝试获取DataSource对象,这个对象即当前连接的数据源

3.那么this.resolvedDataSources在哪里维护? AbstractRoutingDataSource类实现了InitializingBean类的afterPropertiesSet()方法, 在bean的所有属性设置完成后变会调用此方法,可以看到this.resolvedDataSources从this.targetDataSources取的信息;

所以只需要改变this.targetDataSources,并且触发afterPropertiesSet(),即可改变this.resolvedDataSources;后续改变determineCurrentLookupKey()的返回值(key),在调用getConnection()时即可获取到指定的数据源

多租户业务背景

多租户业务场景下,往往每个租户都独立一个数据库(是否独立数据源实例根据实际需要处理),每个租户的数据在数据库层面先做了隔离,在开展详细业务编写时就可以不用考虑不同租户的数据会混淆。但是随之而来的就是数据源灵活切换的需求,需要封装一套方法,在业务编写时可以根据提供的租户代码便捷的切换到对应的数据源

提供的切换方式

1.注解方式切换 提供一个注解,可以根据租户代码切换,也可以根据配置文件中写定的数据源名称切换

2.直接调用方法方式切换 提供一个租户rds切换类,在编写业务代码时调用方法切换,该方式可以让租户代码以变量形式传递,无需提前知道

实现步骤概要

1.添加pom依赖、配置数据源信息 2.编写数据源配置类,将数据源配置信息注入到容器 3.编写DynamicDataSource类继承AbstractRoutingDataSource抽象类,维护当前数据源信息,提供切换方法 4.编写租户rds切换类,业务切换数据源时统一调用此类 5.编写自定义注解 6.编写切面类,将连接点直接设定在编写的自定义注解上,根据参数等调用rds切换类切换数据源 7.异常类、异常枚举类,规范异常抛出

详细步骤

1.pom依赖添加、配置数据源信息

pom.xml

<dependencies><!--mysqlps:由于连接的数据库是5.6所以用较老的包,读者可以根据数据库版本选择--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version><scope>runtime</scope></dependency><!--aop--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!--druid数据源--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency></dependencies>

application.yml

#主配置spring:#数据源配置datasource:#修改数据源为druidtype:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本#druid配置druid:#主数据源master:driver-class-name:com.mysql.jdbc.Driver#默认数据库连接(配置库)url:jdbc:mysql://xxx:xxx/config?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxx#递增db配置db1:driver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本url:jdbc:mysql://xxx:xxx/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxxinitial-size:5#初始化时建立物理连接的个数max-active:30#最大连接池数量min-idle:5#最小连接池数量max-wait:60000#获取连接时最大等待时间,单位毫秒time-between-eviction-runs-millis:60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒min-evictable-idle-time-millis:300000#连接保持空闲而不被驱逐的最小时间validation-query:SELECT1FROMDUAL#用来检测连接是否有效的sql,要求是一个查询语句test-while-idle:true#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-on-borrow:false#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。test-on-return:false#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。pool-prepared-statements:true#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。max-pool-prepared-statement-per-connection-size:50#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。filters:stat,wall,log4j2#配置监控统计拦截的filters,去掉后监控界面sql无法统计;配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#通过connectProperties属性来打开mergeSql功能;慢SQL记录use-global-data-source-stat:true#合并多个DruidDataSource的监控数据stat-view-servlet:allow:''#IP白名单(没有配置或者为空,则允许所有访问)allow:127.0.0.1,192.168.163.1deny:''#IP黑名单(存在共同时,deny优先于allow)login-password:xxxxxx#登录密码login-username:admin#登录名reset-enable:false#禁用HTML页面上的“ResetAll”功能url-pattern:/druid/*#配置DruidStatViewServletweb-stat-filter:#配置DruidStatFilterenabled:trueexclusions:'*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'url-pattern:/*

1.配置里面包含了一些druid的配置,可以根据业务需要自行配置 2.其中,spring.datasource.druid.master为主数据源,也是配置库数据源,租户库数据源连接信息会在配置库中获取,spring.datasource.druid.db1为递增数据源,db1可以命名为具体的业务库名称,这里仅仅方便理解取名为db1


2.编写数据源配置类,将数据源配置信息注入到容器

数据源配置类DataSourceConfig

@Configuration@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})//排除DataSourceAutoConfiguration的自动配置,避免环形调用publicclassDataSourceConfig{/***默认数据源**@return*/@Bean(DataSourceConstant.DATA_SOURCE_MASTER)@ConfigurationProperties("spring.datasource.druid.master")publicDataSourcedataSourceMaster(){returnDruidDataSourceBuilder.create().build();}/***递增数据源**@return*/@Bean(DataSourceConstant.DATA_SOURCE_DB_1)@ConfigurationProperties("spring.datasource.druid.db1")publicDataSourcedataSourceDb1(){returnDruidDataSourceBuilder.create().build();}/***设置动态数据源为主数据源**@return*/@Bean@PrimarypublicDynamicDataSourcedataSource(){//将数据源设置进mapDynamicDataSource.setDataSourceMap(DataSourceConstant.DATA_SOURCE_MASTER,dataSourceMaster());DynamicDataSource.setDataSourceMap(DataSourceConstant.DATA_SOURCE_DB_1,dataSourceDb1());DynamicDataSourcedynamicDataSource=newDynamicDataSource();//使用Map保存多个数据源,并设置到动态数据源对象中,这个值最终会在afterPropertiesSet中被设置到resolvedDataSources上dynamicDataSource.setTargetDataSources(DynamicDataSource.dataSourceMap);returndynamicDataSource;}}

数据源常量类

publicclassDataSourceConstant{privateDataSourceConstant(){}/***这里的命名统一在配置文件命名的基础上加dataSource前缀且改小驼峰*默认数据源名称*/publicstaticfinalStringDATA_SOURCE_MASTER="dataSourceMaster";/***递增可配数据源名称*这里的命名统一在配置文件命名的基础上加dataSource前缀且改小驼峰*后面可接着db2...dbn也可以根据*/publicstaticfinalStringDATA_SOURCE_DB_1="dataSourceDb1";}

此处先往DynamicDataSource.dataSourceMap将两个配置好的数据源连接信息写入,并设置到动态数据源对象中,这个值最终会在afterPropertiesSet中被设置到resolvedDataSources上


3.编写DynamicDataSource类继承AbstractRoutingDataSource抽象类,维护当前数据源信息,提供切换方法

动态数据源类DynamicDataSource

publicclassDynamicDataSourceextendsAbstractRoutingDataSource{/***存储当前线程的数据源key*/privatestaticfinalThreadLocal<String>DATA_SOURCE_KEY=ThreadLocal.withInitial(()->DataSourceConstant.DATA_SOURCE_MASTER);/***数据源map*/publicstaticMap<Object,Object>dataSourceMap=newConcurrentHashMap<>(1000);/***获取数据源key**@return*/publicstaticStringgetDataSourceKey(){returnDynamicDataSource.DATA_SOURCE_KEY.get();}/***设置数据源key**@paramkey*/publicstaticvoidsetDataSourceKey(Stringkey){DynamicDataSource.DATA_SOURCE_KEY.set(key);}/***移除默认数据源key*/publicstaticvoidremove(){DynamicDataSource.DATA_SOURCE_KEY.remove();}/***切换成默认的数据源*/publicstaticvoidsetDataSourceDefault(){setDataSource(DataSourceConstant.DATA_SOURCE_MASTER);}/***切换成指定数据源前提是dataSourceMap中有该key*外层调用时需要判断下map是否有,可靠性交给外层维护**@paramdataSource*/publicstaticvoidsetDataSource(StringdataSource){setDataSourceKey(dataSource);//InitializingBean.afterPropertiesSet()是,实例化后,bean的所有属性初始化后调用;但是如果该bean是直接从容器中拿的,并不需要实例化动作//这里直接拿到dataSource,手动触发一下,让AbstractRoutingDataSource.resolvedDataSources重新赋值,取到本类维护的map的值DynamicDataSourcedynamicDataSource=(DynamicDataSource)SpringContextUtil.getBean("dataSource");dynamicDataSource.afterPropertiesSet();}/***获取租户数据源配置**@paramtenantCode*@return*/publicstaticObjectgetDataSourceMap(StringtenantCode){returnDynamicDataSource.dataSourceMap.get(tenantCode);}/***设置map**@paramdataSourceName*@returnvoid*@authorLinzs*@date2021/8/2811:53**/publicstaticvoidsetDataSourceMap(StringdataSourceName,ObjectdataSource){dataSourceMap.put(dataSourceName,dataSource);}/***设置map**@paramdataSourceName*@returnvoid*@authorLinzs*@date2021/8/2811:53**/publicstaticvoidsetDataSourceMap(StringdataSourceName){dataSourceMap.put(dataSourceName,SpringContextUtil.getBean(dataSourceName));}/***设置租户数据源配置**@paramrdsConfig*@return*/publicstaticvoidsetDataSourceMap(RdsConfigrdsConfig){DynamicDataSource.dataSourceMap.put(rdsConfig.getTenantCode(),getDruidDataSource(rdsConfig));}/***获取DruidDataSource**@paramrdsConfig*@return*/privatestaticDruidDataSourcegetDruidDataSource(RdsConfigrdsConfig){DruidDataSourcedruidDataSource=newDruidDataSource();druidDataSource.setUrl("jdbc:mysql://"+rdsConfig.getDbUrl()+":"+rdsConfig.getDbPort()+"/"+rdsConfig.getDbName()+"?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&autoReconnect=true&serverTimezone=Asia/Shanghai");druidDataSource.setUsername(rdsConfig.getDbAccount());druidDataSource.setPassword(rdsConfig.getDbPassword());returndruidDataSource;}/***重写determineCurrentLookupKey方法**@returnjava.lang.Object*@date2021/8/2812:14**/@OverrideprotectedObjectdetermineCurrentLookupKey(){returngetDataSourceKey();}}

维护了一个key,用于表示当前用的是哪个数据源

维护了一个map,用于springboot获取数据源信息

重写determineCurrentLookupKey方法,可参照上面源码解读理解


4.编写租户rds切换类,业务切换数据源时统一调用此类

RdsConfig类,该javabean描述rds的连接信息

@DatapublicclassRdsConfigimplementsSerializable{privatestaticfinallongserialVersionUID=1L;/***租户编码*/privateStringtenantCode;/***数据库URL*/privateStringdbUrl;/***数据库端口*/privateStringdbPort;/***数据库名称*/privateStringdbName;/***数据库账号*/privateStringdbAccount;/***数据库密码*/privateStringdbPassword;}

具体rds切换服务类:TenantRdsServiceImpl类,实现TenantRdsService接口,这里不贴出来了

@Service@Slf4jpublicclassTenantRdsServiceImplimplementsTenantRdsService{@AutowiredprivateTenantMappertenantMapper;@AutowiredprivateRdsMapperrdsMapper;/***获取rds配置**@paramtenantCode*@date2021/8/2813:53**/@OverridepublicRdsConfiggetRdsConfig(StringtenantCode){//根据租户代码取租户表Tenanttenant=tenantMapper.selectByTenantCode(tenantCode);if(null==tenant){returnnull;}//取rds表Rdsrds=rdsMapper.selectByPrimaryKey(tenant.getRdsId());if(null==rds){returnnull;}//转换为rds配置RdsConfigrdsConfig=newRdsConfig();rdsConfig.setDbUrl(rds.getHost());rdsConfig.setTenantCode(tenantCode);rdsConfig.setDbName(tenant.getDbName());rdsConfig.setDbAccount(rds.getAccount());rdsConfig.setDbPassword(rds.getPwd());rdsConfig.setDbPort(String.valueOf(rds.getPort()));returnrdsConfig;}/***根据租户代码切换rds连接,同一个线程内rds配置只会查一次**@paramtenantCode*@date2021/8/2813:16**/@OverridepublicvoidswitchRds(StringtenantCode){if(StringUtils.isBlank(tenantCode)){thrownewTenantCodeIsBlankException();}//如果当前已是这个租户rds则直接返回if(tenantCode.equals(DynamicDataSource.getDataSourceKey())){return;}//如果本地已有则不查了改rds需要重启服务if(null==DynamicDataSource.getDataSourceMap(tenantCode)){//如果当前不是配置库则先切回配置库if(!DataSourceConstant.DATA_SOURCE_MASTER.equals(DynamicDataSource.getDataSourceKey())){DynamicDataSource.setDataSourceDefault();}//获取rds配置RdsConfigrdsConfig=getRdsConfig(tenantCode);if(null==rdsConfig){thrownewRdsNotFoundException();}DynamicDataSource.setDataSourceMap(rdsConfig);}//切换到业务库DynamicDataSource.setDataSource(tenantCode);}/***根据数据源名称切换rds连接,同一个线程内rds配置只会查一次**@paramdataSourceName*@date2021/8/2813:16**/@OverridepublicvoidswitchRdsByDataSourceName(StringdataSourceName){if(StringUtils.isBlank(dataSourceName)){thrownewDataSourceNameIsEmptyException();}//如果当前已是这个数据源直接返回if(dataSourceName.equals(DynamicDataSource.getDataSourceKey())){return;}//如果本地已有则不查了改rds需要重启服务if(null==DynamicDataSource.getDataSourceMap(dataSourceName)){thrownewDataSourceNotExistException();}//切换DynamicDataSource.setDataSource(dataSourceName);}}

1.这里用到了两张表,一张是租户表(tenant)用于存储租户代码与rds的对应关系,另一张是DB连接信息(rds)表,用于存储数据源连接信息,具体的mapper和javabean的代码这里就不贴出来了,根据需求建表具体实现即可 2.提供了三个方法分别是根据租户代码获取rds连接信息,根据租户代码切换rds,根据数据源名称切换rds,切换方法中对当前连接信息做了判断,不会重复切换,也不会重复查配置库获取rds信息


5.编写自定义注解

自定义注解 @SwitchMasterRds

/***切换至主数据源-自定义注解*这个仅为了方便使用,用SwitchRds注解指定为默认数据源也可以实现*/@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public@interfaceSwitchMasterRds{}

自定义注解 @SwitchRds

/***切换数据源-自定义注解*///注解作用目标;ElementType.METHOD表示该注解会用在方法上;ElementType.TYPE表示该注解会用在类,接口,枚举;@Target({ElementType.METHOD,ElementType.TYPE})//注解策略属性;RetentionPolicy.RUNTIME表示注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在@Retention(RetentionPolicy.RUNTIME)public@interfaceSwitchRds{/***根据数据源bean切换数据源*此处可以切换的数据源在DataSourceConfig配置类中*同时指定了tenantCode则这个优先*/StringdataSource()default"";/***动态切换-根据租户代码切换数据源*/StringtenantCode()default"";}

1.SwitchRds注解既可以用租户代码切换rds,又可以使用数据源名称切换 2.SwitchMasterRds注解是为了方便切换成主数据源而添加的


6.编写切面类

SwitchMasterRds注解的切面类SwitchMasterRdsAspect

@Aspect@Component@Slf4jpublicclassSwitchMasterRdsAspect{/***租户rds服务类*/@AutowiredprivateTenantRdsServicetenantRdsServiceImpl;/***切点*连接点:直接指定为注解*注意:com.xxx.SwitchMasterRds这里包名自行修改*@date2021/8/2714:26**/@Pointcut("@annotation(com.xxx.SwitchMasterRds)")publicvoidmyPointcut(){}/***环绕通知**@returnjava.lang.Object*@date2021/8/2714:26**/@Around(value="myPointcut()")publicObjectaround(ProceedingJoinPointpjp)throwsThrowable{Objectproceed;try{tenantRdsServiceImpl.switchRdsByDataSourceName(DataSourceConstant.DATA_SOURCE_MASTER);//执行proceed=pjp.proceed();}finally{//todo这里需要做移除切换的数据源也可以,但是如果没移除再下次切换的时候会先切换到配置库}returnproceed;}}

SwitchRds注解的切面类SwitchRdsAspect

#主配置spring:#数据源配置datasource:#修改数据源为druidtype:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本#druid配置druid:#主数据源master:driver-class-name:com.mysql.jdbc.Driver#默认数据库连接(配置库)url:jdbc:mysql://xxx:xxx/config?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxx#递增db配置db1:driver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本url:jdbc:mysql://xxx:xxx/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxxinitial-size:5#初始化时建立物理连接的个数max-active:30#最大连接池数量min-idle:5#最小连接池数量max-wait:60000#获取连接时最大等待时间,单位毫秒time-between-eviction-runs-millis:60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒min-evictable-idle-time-millis:300000#连接保持空闲而不被驱逐的最小时间validation-query:SELECT1FROMDUAL#用来检测连接是否有效的sql,要求是一个查询语句test-while-idle:true#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-on-borrow:false#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。test-on-return:false#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。pool-prepared-statements:true#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。max-pool-prepared-statement-per-connection-size:50#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。filters:stat,wall,log4j2#配置监控统计拦截的filters,去掉后监控界面sql无法统计;配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#通过connectProperties属性来打开mergeSql功能;慢SQL记录use-global-data-source-stat:true#合并多个DruidDataSource的监控数据stat-view-servlet:allow:''#IP白名单(没有配置或者为空,则允许所有访问)allow:127.0.0.1,192.168.163.1deny:''#IP黑名单(存在共同时,deny优先于allow)login-password:xxxxxx#登录密码login-username:admin#登录名reset-enable:false#禁用HTML页面上的“ResetAll”功能url-pattern:/druid/*#配置DruidStatViewServletweb-stat-filter:#配置DruidStatFilterenabled:trueexclusions:'*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'url-pattern:/*0

这里将连接点直接设定在编写的自定义注解上,根据参数等调用rds切换类切换数据源


7.异常类、异常枚举类

ErrorInfo接口,规范异常枚举类

#主配置spring:#数据源配置datasource:#修改数据源为druidtype:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本#druid配置druid:#主数据源master:driver-class-name:com.mysql.jdbc.Driver#默认数据库连接(配置库)url:jdbc:mysql://xxx:xxx/config?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxx#递增db配置db1:driver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本url:jdbc:mysql://xxx:xxx/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxxinitial-size:5#初始化时建立物理连接的个数max-active:30#最大连接池数量min-idle:5#最小连接池数量max-wait:60000#获取连接时最大等待时间,单位毫秒time-between-eviction-runs-millis:60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒min-evictable-idle-time-millis:300000#连接保持空闲而不被驱逐的最小时间validation-query:SELECT1FROMDUAL#用来检测连接是否有效的sql,要求是一个查询语句test-while-idle:true#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-on-borrow:false#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。test-on-return:false#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。pool-prepared-statements:true#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。max-pool-prepared-statement-per-connection-size:50#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。filters:stat,wall,log4j2#配置监控统计拦截的filters,去掉后监控界面sql无法统计;配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#通过connectProperties属性来打开mergeSql功能;慢SQL记录use-global-data-source-stat:true#合并多个DruidDataSource的监控数据stat-view-servlet:allow:''#IP白名单(没有配置或者为空,则允许所有访问)allow:127.0.0.1,192.168.163.1deny:''#IP黑名单(存在共同时,deny优先于allow)login-password:xxxxxx#登录密码login-username:admin#登录名reset-enable:false#禁用HTML页面上的“ResetAll”功能url-pattern:/druid/*#配置DruidStatViewServletweb-stat-filter:#配置DruidStatFilterenabled:trueexclusions:'*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'url-pattern:/*1

处理异常枚举类,将所有错误类型以及错误代码枚举出来

#主配置spring:#数据源配置datasource:#修改数据源为druidtype:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本#druid配置druid:#主数据源master:driver-class-name:com.mysql.jdbc.Driver#默认数据库连接(配置库)url:jdbc:mysql://xxx:xxx/config?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxx#递增db配置db1:driver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本url:jdbc:mysql://xxx:xxx/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxxinitial-size:5#初始化时建立物理连接的个数max-active:30#最大连接池数量min-idle:5#最小连接池数量max-wait:60000#获取连接时最大等待时间,单位毫秒time-between-eviction-runs-millis:60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒min-evictable-idle-time-millis:300000#连接保持空闲而不被驱逐的最小时间validation-query:SELECT1FROMDUAL#用来检测连接是否有效的sql,要求是一个查询语句test-while-idle:true#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-on-borrow:false#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。test-on-return:false#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。pool-prepared-statements:true#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。max-pool-prepared-statement-per-connection-size:50#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。filters:stat,wall,log4j2#配置监控统计拦截的filters,去掉后监控界面sql无法统计;配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#通过connectProperties属性来打开mergeSql功能;慢SQL记录use-global-data-source-stat:true#合并多个DruidDataSource的监控数据stat-view-servlet:allow:''#IP白名单(没有配置或者为空,则允许所有访问)allow:127.0.0.1,192.168.163.1deny:''#IP黑名单(存在共同时,deny优先于allow)login-password:xxxxxx#登录密码login-username:admin#登录名reset-enable:false#禁用HTML页面上的“ResetAll”功能url-pattern:/druid/*#配置DruidStatViewServletweb-stat-filter:#配置DruidStatFilterenabled:trueexclusions:'*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'url-pattern:/*2

处理异常基类,所有的处理异常全部继承该类,其保存ErrorInfo信息,可以方便获取错误代码等

#主配置spring:#数据源配置datasource:#修改数据源为druidtype:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本#druid配置druid:#主数据源master:driver-class-name:com.mysql.jdbc.Driver#默认数据库连接(配置库)url:jdbc:mysql://xxx:xxx/config?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxx#递增db配置db1:driver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本url:jdbc:mysql://xxx:xxx/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxxinitial-size:5#初始化时建立物理连接的个数max-active:30#最大连接池数量min-idle:5#最小连接池数量max-wait:60000#获取连接时最大等待时间,单位毫秒time-between-eviction-runs-millis:60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒min-evictable-idle-time-millis:300000#连接保持空闲而不被驱逐的最小时间validation-query:SELECT1FROMDUAL#用来检测连接是否有效的sql,要求是一个查询语句test-while-idle:true#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-on-borrow:false#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。test-on-return:false#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。pool-prepared-statements:true#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。max-pool-prepared-statement-per-connection-size:50#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。filters:stat,wall,log4j2#配置监控统计拦截的filters,去掉后监控界面sql无法统计;配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#通过connectProperties属性来打开mergeSql功能;慢SQL记录use-global-data-source-stat:true#合并多个DruidDataSource的监控数据stat-view-servlet:allow:''#IP白名单(没有配置或者为空,则允许所有访问)allow:127.0.0.1,192.168.163.1deny:''#IP黑名单(存在共同时,deny优先于allow)login-password:xxxxxx#登录密码login-username:admin#登录名reset-enable:false#禁用HTML页面上的“ResetAll”功能url-pattern:/druid/*#配置DruidStatViewServletweb-stat-filter:#配置DruidStatFilterenabled:trueexclusions:'*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'url-pattern:/*3

具体的异常类,直接继承处理异常基类,文中主动抛出的异常全是这样方式编写,这里就不一一列举了

#主配置spring:#数据源配置datasource:#修改数据源为druidtype:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本#druid配置druid:#主数据源master:driver-class-name:com.mysql.jdbc.Driver#默认数据库连接(配置库)url:jdbc:mysql://xxx:xxx/config?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxx#递增db配置db1:driver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本url:jdbc:mysql://xxx:xxx/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxxinitial-size:5#初始化时建立物理连接的个数max-active:30#最大连接池数量min-idle:5#最小连接池数量max-wait:60000#获取连接时最大等待时间,单位毫秒time-between-eviction-runs-millis:60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒min-evictable-idle-time-millis:300000#连接保持空闲而不被驱逐的最小时间validation-query:SELECT1FROMDUAL#用来检测连接是否有效的sql,要求是一个查询语句test-while-idle:true#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-on-borrow:false#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。test-on-return:false#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。pool-prepared-statements:true#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。max-pool-prepared-statement-per-connection-size:50#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。filters:stat,wall,log4j2#配置监控统计拦截的filters,去掉后监控界面sql无法统计;配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#通过connectProperties属性来打开mergeSql功能;慢SQL记录use-global-data-source-stat:true#合并多个DruidDataSource的监控数据stat-view-servlet:allow:''#IP白名单(没有配置或者为空,则允许所有访问)allow:127.0.0.1,192.168.163.1deny:''#IP黑名单(存在共同时,deny优先于allow)login-password:xxxxxx#登录密码login-username:admin#登录名reset-enable:false#禁用HTML页面上的“ResetAll”功能url-pattern:/druid/*#配置DruidStatViewServletweb-stat-filter:#配置DruidStatFilterenabled:trueexclusions:'*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'url-pattern:/*4

使用

1.注解方式

#主配置spring:#数据源配置datasource:#修改数据源为druidtype:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本#druid配置druid:#主数据源master:driver-class-name:com.mysql.jdbc.Driver#默认数据库连接(配置库)url:jdbc:mysql://xxx:xxx/config?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxx#递增db配置db1:driver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本url:jdbc:mysql://xxx:xxx/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxxinitial-size:5#初始化时建立物理连接的个数max-active:30#最大连接池数量min-idle:5#最小连接池数量max-wait:60000#获取连接时最大等待时间,单位毫秒time-between-eviction-runs-millis:60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒min-evictable-idle-time-millis:300000#连接保持空闲而不被驱逐的最小时间validation-query:SELECT1FROMDUAL#用来检测连接是否有效的sql,要求是一个查询语句test-while-idle:true#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-on-borrow:false#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。test-on-return:false#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。pool-prepared-statements:true#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。max-pool-prepared-statement-per-connection-size:50#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。filters:stat,wall,log4j2#配置监控统计拦截的filters,去掉后监控界面sql无法统计;配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#通过connectProperties属性来打开mergeSql功能;慢SQL记录use-global-data-source-stat:true#合并多个DruidDataSource的监控数据stat-view-servlet:allow:''#IP白名单(没有配置或者为空,则允许所有访问)allow:127.0.0.1,192.168.163.1deny:''#IP黑名单(存在共同时,deny优先于allow)login-password:xxxxxx#登录密码login-username:admin#登录名reset-enable:false#禁用HTML页面上的“ResetAll”功能url-pattern:/druid/*#配置DruidStatViewServletweb-stat-filter:#配置DruidStatFilterenabled:trueexclusions:'*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'url-pattern:/*5

2.业务代码使用方式

#主配置spring:#数据源配置datasource:#修改数据源为druidtype:com.alibaba.druid.pool.DruidDataSourcedriver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本#druid配置druid:#主数据源master:driver-class-name:com.mysql.jdbc.Driver#默认数据库连接(配置库)url:jdbc:mysql://xxx:xxx/config?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxx#递增db配置db1:driver-class-name:com.mysql.jdbc.Driver#这个要根据mysql-connector-java版本url:jdbc:mysql://xxx:xxx/mydb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername:xxxpassword:xxxinitial-size:5#初始化时建立物理连接的个数max-active:30#最大连接池数量min-idle:5#最小连接池数量max-wait:60000#获取连接时最大等待时间,单位毫秒time-between-eviction-runs-millis:60000#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒min-evictable-idle-time-millis:300000#连接保持空闲而不被驱逐的最小时间validation-query:SELECT1FROMDUAL#用来检测连接是否有效的sql,要求是一个查询语句test-while-idle:true#建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。test-on-borrow:false#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。test-on-return:false#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。pool-prepared-statements:true#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。max-pool-prepared-statement-per-connection-size:50#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。filters:stat,wall,log4j2#配置监控统计拦截的filters,去掉后监控界面sql无法统计;配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#通过connectProperties属性来打开mergeSql功能;慢SQL记录use-global-data-source-stat:true#合并多个DruidDataSource的监控数据stat-view-servlet:allow:''#IP白名单(没有配置或者为空,则允许所有访问)allow:127.0.0.1,192.168.163.1deny:''#IP黑名单(存在共同时,deny优先于allow)login-password:xxxxxx#登录密码login-username:admin#登录名reset-enable:false#禁用HTML页面上的“ResetAll”功能url-pattern:/druid/*#配置DruidStatViewServletweb-stat-filter:#配置DruidStatFilterenabled:trueexclusions:'*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'url-pattern:/*6

作者:巴菲爽


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/SpringBoot/343.html