mybatisAOP多数据源配置(使用阿里数据库连接池)

由于项目中需要使用数据源,用的网上开源的项目,之前使用网上通用的多数据源配置,没有切换成功,于是采用了AOP来切换数据源。

(此处只贴出关于多数据源和其他部分的一些配置)

spring-context.xml

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <beans xmlns="http://www.springframework.org/schema/beans" 
  3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4     xmlns:context="http://www.springframework.org/schema/context" 
  5     xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
  6     xmlns:aop="http://www.springframework.org/schema/aop" 
  7     xmlns:jee="http://www.springframework.org/schema/jee" 
  8     xmlns:tx="http://www.springframework.org/schema/tx"
  9     xmlns:util="http://www.springframework.org/schema/util"
 10     xmlns:task="http://www.springframework.org/schema/task" 
 11     xsi:schemaLocation="
 12         http://www.springframework.org/schema/beans 
 13         http://www.springframework.org/schema/beans/spring-beans-4.1.xsd 
 14         http://www.springframework.org/schema/context 
 15         http://www.springframework.org/schema/context/spring-context-4.1.xsd 
 16         http://www.springframework.org/schema/jdbc 
 17         http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd 
 18         http://www.springframework.org/schema/aop 
 19          http://www.springframework.org/schema/aop/spring-aop.xsd 
 20         http://www.springframework.org/schema/jee 
 21         http://www.springframework.org/schema/jee/spring-jee-4.1.xsd 
 22         http://www.springframework.org/schema/lang 
 23          http://www.springframework.org/schema/lang/spring-lang.xsd 
 24         http://www.springframework.org/schema/tx 
 25         http://www.springframework.org/schema/tx/spring-tx-4.1.xsd 
 26         http://www.springframework.org/schema/util 
 27         http://www.springframework.org/schema/util/spring-util-4.1.xsd 
 28         http://www.springframework.org/schema/task 
 29         http://www.springframework.org/schema/task/spring-task-4.1.xsd"
 30     default-lazy-init="true">
 31 
 32     <description>Spring Configuration</description>
 33     
 34     <!-- 加载配置属性文件 -->
 35     <context:property-placeholder ignore-unresolvable="true" location="classpath:jeesite.properties" />
 36     
 37     <!-- 加载应用属性实例,可通过  @Value("#{APP_PROP['jdbc.driver']}") String jdbcDriver 方式引用 -->
 38     <util:properties id="APP_PROP" location="classpath:jeesite.properties" local-override="true"/>
 39     
 40     <!-- 使用Annotation自动注册Bean,解决事物失效问题:在主容器中不扫描@Controller注解,在SpringMvc中只扫描@Controller注解。  -->
 41     <context:component-scan base-package="com.vcard"><!-- base-package 如果多个,用“,”分隔 -->
 42         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
 43     </context:component-scan>
 44     
 45     <bean id="jedisUtil" class="h2o.common.thirdparty.redis.JedisUtil">
 46         <constructor-arg>
 47             <list>
 48                 <value>localhost:6379</value>
 49                 <value>localhost:6379</value>
 50             </list>
 51         </constructor-arg>
 52     </bean>
 53     
 54      <!-- MyBatis begin -->
 55     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
 56         <!-- <property name="dataSource" ref="dataSource"/> -->
 57         <property name="dataSource" ref="dynamicDataSource"/>
 58         <property name="typeAliasesPackage" value="com.vcard"/>
 59         <property name="typeAliasesSuperType" value="com.vcard.common.persistence.BaseEntity"/>
 60         <property name="mapperLocations" value="classpath:/mappings/**/*.xml"/>
 61         <property name="configLocation" value="classpath:/mybatis-config.xml"></property>
 62     </bean>
 63     
 64     <!-- 扫描basePackage下所有以@MyBatisDao注解的接口 -->
 65     <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
 66         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
 67         <property name="basePackage" value="com.vcard"/>
 68         <property name="annotationClass" value="com.vcard.common.persistence.annotation.MyBatisDao"/>
 69     </bean>
 70     
 71     <!-- 动态数据源 -->
 72     <bean id="dynamicDataSource" class="com.vcard.common.db.DynamicDataSource">
 73          <property name="defaultTargetDataSource" ref="dataSource"/>
 74          <property name="targetDataSources">
 75              <map key-type="java.lang.String">
 76                  <!-- <entry key="dataSource" value-ref="dataSource"/> -->
 77                  <entry key="dataSource2" value-ref="dataSource2"/>
 78              </map>
 79          </property>
 80     </bean>
 81     
 82      <!-- 定义事务 -->
 83     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 84         <property name="dataSource" ref="dynamicDataSource" />
 85     </bean>
 86     
 87     <!-- 配置 Annotation 驱动,扫描@Transactional注解的类定义事务  -->
 88     <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
 89     
 90     <!-- 拦截器方式配置事务 -->
 91     <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
 92         <tx:attributes>
 93             <tx:method name="get*" propagation="REQUIRED" read-only="true"/>
 94             <tx:method name="find*" propagation="REQUIRED" read-only="true"/>
 95             <tx:method name="list*" propagation="REQUIRED" read-only="true"/>
 96             <tx:method name="insert*" rollback-for="java.lang.Exception" propagation="REQUIRED" read-only="false"/>
 97             <tx:method name="create*" rollback-for="java.lang.Exception" propagation="REQUIRED" read-only="false"/>
 98             <tx:method name="update*" rollback-for="java.lang.Exception" propagation="REQUIRED" read-only="false"/>
 99             <tx:method name="save*" rollback-for="java.lang.Exception" propagation="REQUIRED" read-only="false"/>
100             <tx:method name="delete*" rollback-for="java.lang.Exception" propagation="REQUIRED" read-only="false"/>
101             <tx:method name="upd*" rollback-for="java.lang.Exception" propagation="REQUIRED" read-only="false"/>
102         </tx:attributes>
103     </tx:advice>
104     
105     <bean id="transactionAdvice" class="com.vcard.common.db.DataSourceAspect"></bean>
106     
107     <aop:config>
108         <aop:pointcut id="transactionPointcut" expression="execution(* com.vcard.second.modules.order.web.*.*(..))" />
109         <aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPointcut"/>
110     </aop:config>
111     
112     <!-- 定义事务 -->
113     <!-- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
114         <property name="dataSource" ref="dataSource" />
115     </bean> -->
116     <!-- MyBatis end -->
117     
118     <!-- 配置 JSR303 Bean Validator 定义 -->
119     <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
120 
121     <!-- 缓存配置 -->
122     <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
123         <property name="configLocation" value="classpath:${ehcache.configFile}" />
124     </bean>
125     
126     <!-- 计划任务配置,用 @Service @Lazy(false)标注类,用@Scheduled(cron = "0 0 2 * * ?")标注方法 -->
127     <task:executor id="executor" pool-size="10"/> <task:scheduler id="scheduler" pool-size="10"/>
128     <task:annotation-driven scheduler="scheduler" executor="executor" proxy-target-class="true"/>
129     
130     <!-- 数据源配置, 使用 BoneCP 数据库连接池 -->
131     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
132         <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
133         <property name="driverClassName" value="${jdbc.driver}" />
134         
135         <!-- 基本属性 url、user、password -->
136         <property name="url" value="${jdbc.url}" />
137         <property name="username" value="${jdbc.username}" />
138         <property name="password" value="${jdbc.password}" />
139         
140         <!-- 配置初始化大小、最小、最大 -->
141         <property name="initialSize" value="${jdbc.pool.init}" />
142         <property name="minIdle" value="${jdbc.pool.minIdle}" /> 
143         <property name="maxActive" value="${jdbc.pool.maxActive}" />
144         
145         <!-- 配置获取连接等待超时的时间 -->
146         <property name="maxWait" value="60000" />
147         
148         <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
149         <property name="timeBetweenEvictionRunsMillis" value="60000" />
150         
151         <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
152         <property name="minEvictableIdleTimeMillis" value="300000" />
153         
154         <property name="validationQuery" value="${jdbc.testSql}" />
155         <property name="testWhileIdle" value="true" />
156         <property name="testOnBorrow" value="false" />
157         <property name="testOnReturn" value="false" />
158         
159         <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用)
160         <property name="poolPreparedStatements" value="true" />
161         <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->
162         
163         <!-- 配置监控统计拦截的filters -->
164         <property name="filters" value="stat" /> 
165     </bean>
166     
167     <!-- 数据源配置, 使用 BoneCP 数据库连接池 -->
168     <bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
169         <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
170         <property name="driverClassName" value="${jdbc2.driver}" />
171         
172         <!-- 基本属性 url、user、password -->
173         <property name="url" value="${jdbc2.url}" />
174         <property name="username" value="${jdbc2.username}" />
175         <property name="password" value="${jdbc2.password}" />
176         
177         <!-- 配置初始化大小、最小、最大 -->
178         <property name="initialSize" value="${jdbc2.pool.init}" />
179         <property name="minIdle" value="${jdbc2.pool.minIdle}" /> 
180         <property name="maxActive" value="${jdbc2.pool.maxActive}" />
181         
182         <!-- 配置获取连接等待超时的时间 -->
183         <property name="maxWait" value="60000" />
184         
185         <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
186         <property name="timeBetweenEvictionRunsMillis" value="60000" />
187         
188         <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
189         <property name="minEvictableIdleTimeMillis" value="300000" />
190         
191         <property name="validationQuery" value="${jdbc.testSql}" />
192         <property name="testWhileIdle" value="true" />
193         <property name="testOnBorrow" value="false" />
194         <property name="testOnReturn" value="false" />
195         
196         <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用)
197         <property name="poolPreparedStatements" value="true" />
198         <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->
199         
200         <!-- 配置监控统计拦截的filters -->
201         <property name="filters" value="stat" /> 
202     </bean>
203 
204     <!-- 数据源配置, 使用应用服务器的数据库连接池 
205     <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/jeesite" />-->
206 
207     <!-- 数据源配置, 不使用连接池 
208     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
209         <property name="driverClassName" value="${jdbc.driver}" />
210         <property name="url" value="${jdbc.url}" />
211         <property name="username" value="${jdbc.username}"/>
212         <property name="password" value="${jdbc.password}"/>
213     </bean>-->
214     
215 </beans>

jeesite.properties

  1 #============================#
  2 #===== Database sttings =====#
  3 #============================#
  4 
  5 #oracle database settings
  6 #jdbc.type=oracle
  7 #jdbc.driver=oracle.jdbc.driver.OracleDriver
  8 #jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
  9 #jdbc.username=jeesite
 10 #jdbc.password=123456
 11 
 12 #mysql database setting
 13 jdbc.type=mysql
 14 jdbc.driver=com.mysql.jdbc.Driver
 15 #jdbc.url=jdbc:mysql://localhost:3306/vcardjeesite?useUnicode=true&characterEncoding=utf-8
 16 #jdbc.username=root
 17 #jdbc.password=123456
 18 jdbc.url=jdbc:mysql://localhost:3306/vcardjeesite?useUnicode=true&characterEncoding=utf-8
 19 jdbc.username=changyue
 20 jdbc.password=cykjdev164123
 21 
 22 jdbc2.type=mysql
 23 jdbc2.driver=com.mysql.jdbc.Driver
 24 jdbc2.url=jdbc:mysql://localhost:3306/newmall?useUnicode=true&characterEncoding=utf-8
 25 jdbc2.username=changyue
 26 jdbc2.password=cykjdev164123
 27 #jdbc2.url=jdbc:mysql://localhost:3306/newmalljeesite?useUnicode=true&characterEncoding=utf-8
 28 #jdbc2.username=root
 29 #jdbc2.password=123456
 30 
 31 #mssql database settings
 32 #jdbc.type=mssql
 33 #jdbc.driver=net.sourceforge.jtds.jdbc.Driver
 34 #jdbc.url=jdbc:jtds:sqlserver://localhost:1433/jeesite
 35 #jdbc.username=sa
 36 #jdbc.password=sa
 37 
 38 #pool settings
 39 jdbc.pool.init=1
 40 jdbc.pool.minIdle=3
 41 jdbc.pool.maxActive=20
 42 
 43 jdbc2.pool.init=1
 44 jdbc2.pool.minIdle=3
 45 jdbc2.pool.maxActive=20
 46 
 47 #jdbc.testSql=SELECT 'x'
 48 jdbc.testSql=SELECT 'x' FROM DUAL
 49 
 50 #redis settings
 51 redis.keyPrefix=vcard
 52 redis.host=localhost
 53 redis.port=6379
 54 
 55 #============================#
 56 #===== System settings ======#
 57 #============================#
 58 
 59 #u4ea7u54c1u4fe1u606fu8bbeu7f6e
 60 productName=u5546u6237u5F00u653Eu5E73u53F0
 61 copyrightYear=2017
 62 version=V1.2.7
 63 
 64 #u6f14u793au6a21u5f0f: u4e0du80fdu64cdu4f5cu548cu4fddu5b58u7684u6a21u5757uff1a sys: area/office/user/role/menu/dict, cms: site/category
 65 demoMode=false
 66 
 67 #u7ba1u7406u57fau7840u8defu5f84, u9700u540cu6b65u4feeu6539uff1aweb.xml
 68 adminPath=/a
 69 
 70 #u524du7aefu57fau7840u8defu5f84
 71 frontPath=/f
 72 
 73 #u7f51u7ad9URLu540eu7f00
 74 urlSuffix=.html
 75 
 76 #u662fu5426u4e0du5141u8bb8u5237u65b0u4e3bu9875uff0cu4e0du5141u8bb8u60c5u51b5u4e0buff0cu5237u65b0u4e3bu9875u4f1au5bfcu81f4u91cdu65b0u767bu5f55
 77 notAllowRefreshIndex=false
 78 
 79 #u662fu5426u5141u8bb8u591au8d26u53f7u540cu65f6u767bu5f55
 80 user.multiAccountLogin=true
 81 
 82 #u5206u9875u914du7f6e
 83 page.pageSize=10
 84 
 85 #u7855u6b63u7ec4u4ef6u662fu5426u4f7fu7528u7f13u5b58
 86 supcan.useCache=false
 87 
 88 #u901au77e5u95f4u9694u65f6u95f4u8bbeu7f6e, u5355u4f4duff1au6bebu79d2, 30s=30000ms, 60s=60000ms
 89 oa.notify.remind.interval=60000
 90 
 91 #============================#
 92 #==== Framework settings ====#
 93 #============================#
 94 
 95 #u4f1au8bddu8d85u65f6uff0c u5355u4f4duff1au6bebu79d2uff0c 20m=1200000ms, 30m=1800000ms, 60m=3600000ms
 96 session.sessionTimeout=1800000
 97 #u4f1au8bddu6e05u7406u95f4u9694u65f6u95f4uff0c u5355u4f4duff1au6bebu79d2uff0c2m=120000msu3002
 98 session.sessionTimeoutClean=120000
 99 
100 #u7f13u5b58u8bbeu7f6e
101 ehcache.configFile=cache/ehcache-local.xml
102 #ehcache.configFile=cache/ehcache-rmi.xml
103 
104 #u7d22u5f15u9875u8defu5f84
105 web.view.index=/a
106 
107 #u89c6u56feu6587u4ef6u5b58u653eu8defu5f84
108 web.view.prefix=/WEB-INF/views/
109 web.view.suffix=.jsp
110 
111 #u6700u5927u6587u4ef6u4e0au4f20u9650u5236uff0cu5355u4f4du5b57u8282. 10M=10*1024*1024(B)=10485760 bytesuff0cu9700u540cu6b65u4feeu6539uff1ackfinder.xml
112 web.maxUploadSize=10485760
113 
114 #u65e5u5fd7u62e6u622au8bbeu7f6euff0cu6392u9664u7684URIuff1bu5305u542b @RequestMappingu6ce8u89e3u7684valueu3002uff08u5df2u4f5cu5e9fuff09
115 #web.logInterceptExcludeUri=/, /login, /sys/menu/tree, /sys/menu/treeData, /oa/oaNotify/self/count
116 #web.logInterceptIncludeRequestMapping=save, delete, import, updateSort
117 
118 #u9759u6001u6587u4ef6u540eu7f00
119 web.staticFile=.css,.js,.png,.jpg,.gif,.jpeg,.bmp,.ico,.swf,.psd,.htc,.htm,.html,.crx,.xpi,.exe,.ipa,.apk
120 
121 #u5355u70b9u767bu5f55CASu8bbeu7f6e
122 cas.server.url=http://127.0.0.1:8080/cas
123 cas.project.url=http://127.0.0.1:8080/vcard
124 
125 #u5de5u4f5cu6d41u8bbeu7f6e
126 activiti.isSynActivitiIndetity=false
127 activiti.export.diagram.path=c:/activiti_diagram
128 #activiti font (windows font: u5b8bu4f53  linux font: simsun)
129 activiti.diagram.activityFontName=u5b8bu4f53
130 activiti.diagram.labelFontName=u5b8bu4f53
131 #5.21.0 u65b0u589eu53c2u6570 ,2016.06.23 u8f66u6811u708e add
132 activiti.diagram.annotationFontName=u5b8bu4f53
133 #activitiu5916u90e8u8868u5355u6839u5730u5740u914du7f6e
134 activiti.form.server.url=
135 
136 #u4e0au4f20u6587u4ef6u7eddu5bf9u8defu5f84, u8defu5f84u4e2du4e0du5141u8bb8u5305u542bu201cuserfilesu201d
137 #userfiles.basedir=D:/jeesite
138 
139 #u5de5u7a0bu8defu5f84uff0cu5728u4ee3u7801u751fu6210u65f6u83b7u53d6u4e0du5230u5de5u7a0bu8defu5f84u65f6uff0cu53efu518du6b64u6307u5b9au7eddu5bf9u8defu5f84u3002
140 #projectPath=D:\workspace\jeesite

DynamicDataSource.java

 1 import org.aspectj.lang.annotation.Aspect;
 2 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 3 import org.springframework.stereotype.Component;
 4 
 5 /**
 6  * 多数据源配置
 7  */
 8 @Component
 9 @Aspect
10 public class DynamicDataSource extends AbstractRoutingDataSource {
11 
12     public DynamicDataSource() {
13     }
14     
15     @Override
16     protected Object determineCurrentLookupKey() {
17         return DBContextHolder.getDbType();
18     }
19     
20     public java.util.logging.Logger getParentLogger() {
21         return null;
22     }
23 }

DBContextHolder.java

 1 public class DBContextHolder {
 2     private static ThreadLocal<String> contextHolder = new ThreadLocal<String>();
 3     public static String Master = "dataSource";
 4     public static String Slave = "dataSource2";
 5     
 6     public DBContextHolder() {
 7     }
 8 
 9     public static String getDbType() {
10         String db = contextHolder.get();
11         if (db == null) {
12             db = Master;
13         }
14         return db;
15     }
16     
17     public static void setDbType(String str) {
18         contextHolder.set(str);
19     }
20     
21     public static void setMater() {
22         contextHolder.set(Master);
23     }
24     
25     public static void serSlave() {
26         contextHolder.set(Slave);
27     }
28     
29     public static void clearDBType() {
30         contextHolder.remove();
31     }
32 }

DataSourceAspect.java

 1 import java.lang.reflect.Method;
 2 
 3 import org.apache.logging.log4j.LogManager;
 4 import org.apache.logging.log4j.Logger;
 5 import org.aspectj.lang.JoinPoint;
 6 import org.springframework.aop.AfterReturningAdvice;
 7 import org.springframework.aop.MethodBeforeAdvice;
 8 import org.springframework.aop.ThrowsAdvice;
 9 
10 public class DataSourceAspect implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {
11     private static final Logger log = LogManager.getLogger(DataSourceAspect.class);
12 
13     public DataSourceAspect() {
14     }
15 
16     public void before(Method m, Object[] args, Object target) throws Throwable {
17         try {
18             if (m != null) {
19                 // 拦截ImsShopOrderController中的方法,切换数据源
20                 if ((m.getName().equals("listImsShopOrder") 
21                         || m.getName().equals("sendGoods") 
22                         || m.getName().equals("cancleSend")) 
23                         && !m.getName().contains("FromMaster")) {
24                     DBContextHolder.setDbType(DBContextHolder.Slave);
25                 } else {
26                     DBContextHolder.setDbType(DBContextHolder.Master);
27                 }
28             }
29         } catch (Exception var5) {
30             log.error("data source aspect error.", var5);
31         }
32 
33     }
34 
35     public void after(JoinPoint point) {
36         log.info("clear db type after method.current id {}",
37                 new Object[] { Long.valueOf(Thread.currentThread().getId()) });
38         DBContextHolder.clearDBType();
39     }
40 
41     public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
42     }
43 
44     public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
45         log.info("current db type {} when exception", new Object[] { DBContextHolder.getDbType() });
46         DBContextHolder.setDbType(DBContextHolder.Master);
47     }
48 }
原文地址:https://www.cnblogs.com/wdpnodecodes/p/8328054.html