*.properties configuration:
<!--data Connection configuration---
Jdbc.type=mysql
Jdbc.driver=com.mysql.jdbc.driver
jdbc.url=jdbc:mysql://localhost:3066/qshop?useunicode=true&characterencoding=utf-8& Usefastdateparsing=false&allowmultiqueries=true&servertimezone=gmt%2b8
Jdbc.username=xxxxx
Jdbc.password=xxxx
<!--data Connection configuration two--
Merchant.jdbc.type=mysql
Merchant.jdbc.driver=com.mysql.jdbc.driver
Merchant.jdbc.url=jdbc:mysql://localhost:3066/qshop_merchant?useunicode=true&characterencoding=utf-8 &usefastdateparsing=false&allowmultiqueries=true&servertimezone=gmt%2b8
Merchant.jdbc.username=xxxx
Merchant.jdbc.password=xxxx
Spring-application.xml configuration:
<!--data source, data source configuration, using Druid database connection pool--
<bean id= "DataSource" class= "Com.alibaba.druid.pool.DruidDataSource" init-method= "Init" destroy-method= "Close" >
<!--data source driver class is not writable, Druid is automatically identified by URL Driverclass-
<property name= "Driverclassname" value= "${jdbc.driver}"/>
<!--basic property URL, user, password--
<property name= "url" value= "${jdbc.url}"/>
<property name= "username" value= "${jdbc.username}"/>
<property name= "Password" value= "${jdbc.password}"/>
<!--configuration initialization size, MIN, max--
<property name= "InitialSize" value= "${jdbc.pool.init}"/>
<property name= "Minidle" value= "${jdbc.pool.minidle}"/>
<property name= "maxactive" value= "${jdbc.pool.maxactive}"/>
<!--configuration Gets the time that the connection waits timeout--
<property name= "maxwait" value= "60000"/>
< how long!--configuration interval to detect idle connections that need to be closed, in milliseconds-and
<property name= "Timebetweenevictionrunsmillis" value= "60000"/>
<!--Configure the minimum time for a connection to survive in a pool, in milliseconds--
<property name= "Minevictableidletimemillis" value= "300000"/>
<property name= "Validationquery" value= "${jdbc.testsql}"/>
<property name= "Testwhileidle" value= "true"/>
<property name= "Testonborrow" value= "false"/>
<property name= "Testonreturn" value= "false"/>
<!--open Pscache and specify the size of Pscache on each connection (Oracle uses)
<property name= "Poolpreparedstatements" value= "true"/>
<property name= "maxpoolpreparedstatementperconnectionsize" value= "/>"--
<!--configuration monitoring statistics intercept filters--
<property name= "Filters" value= "stat"/>
</bean>
<!--data source two, business data source configuration, using Druid database connection pool--
<bean id= "Merchantdatasource" class= "Com.alibaba.druid.pool.DruidDataSource" init-method= "Init" destroy-method= "Close" >
<!--data source driver class is not writable, Druid is automatically identified by URL Driverclass-
<property name= "Driverclassname" value= "${merchant.jdbc.driver}"/>
<!--basic property URL, user, password--
<property name= "url" value= "${merchant.jdbc.url}"/>
<property name= "username" value= "${merchant.jdbc.username}"/>
<property name= "Password" value= "${merchant.jdbc.password}"/>
<!--configuration initialization size, MIN, max--
<property name= "InitialSize" value= "${jdbc.pool.init}"/>
<property name= "Minidle" value= "${jdbc.pool.minidle}"/>
<property name= "maxactive" value= "${jdbc.pool.maxactive}"/>
<!--configuration Gets the time that the connection waits timeout--
<property name= "maxwait" value= "60000"/>
< how long!--configuration interval to detect idle connections that need to be closed, in milliseconds-and
<property name= "Timebetweenevictionrunsmillis" value= "60000"/>
<!--Configure the minimum time for a connection to survive in a pool, in milliseconds--
<property name= "Minevictableidletimemillis" value= "300000"/>
<property name= "Validationquery" value= "${jdbc.testsql}"/>
<property name= "Testwhileidle" value= "true"/>
<property name= "Testonborrow" value= "false"/>
<property name= "Testonreturn" value= "false"/>
<!--open Pscache and specify the size of Pscache on each connection (Oracle uses)
<property name= "Poolpreparedstatements" value= "true"/>
<property name= "maxpoolpreparedstatementperconnectionsize" value= "/>"--
<!--configuration monitoring statistics intercept filters--
<property name= "Filters" value= "stat"/>
</bean>
<!--configuring Dynamic Data Sources--
<bean id= "Dynamicdatasource" class= "Com.yryz.qshop.modules.dynamiclink.DynamicDataSource" >
<property name= "Targetdatasources" >
<map key-type= "Java.lang.String" >
<!--Specify the LookupKey and the corresponding data source
<entry key= "DataSource" value-ref= "DataSource" ></entry>
<entry key= "Merchantdatasource" value-ref= "Merchantdatasource" ></entry>
</map>
</property>
<!--Here you can specify the default data source {It is best not to specify, there is a pit}--> after the specified
<!--<property name= "Defaulttargetdatasource" ref= "DataSource"/>--
</bean>
<bean id= "Datasourceaspect" class= "Com.yryz.qshop.modules.dynamiclink.aspect.DataSourceAspect"/>
<aop:config>
<aop:aspect ref= "Datasourceaspect" >
<aop:pointcut id= "datasourcepointcut" expression= "Execution (* com.yryz.qshop.modules.merchantremote.service.*. *(..))" />
<aop:before pointcut-ref= "Datasourcepointcut" method= "intercept"/>
</aop:aspect>
</aop:config>
Dynamic Data Source classes:
Dynamicdatasourceholder.java
Package com.yryz.qshop.modules.dynamiclink;
public class Dynamicdatasourceholder {
/**
* Note: The data source ID is saved in the thread variable to avoid interfering with the data source when the multi-threading operation
*/
private static final threadlocal<string> Thread_data_source = new threadlocal<string> ();
public static String Getdatasource () {
return Thread_data_source.get ();
}
public static void Setdatasource (String dataSource) {
Thread_data_source.set (DataSource);
}
public static void Cleardatasource () {
Thread_data_source.remove ();
}
}
Dynamicdatasource.java
Package com.yryz.qshop.modules.dynamiclink;
Import Org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class Dynamicdatasource extends abstractroutingdatasource{
@Override
Protected Object Determinecurrentlookupkey () {
Get the data source identity from a custom location
return Dynamicdatasourceholder.getdatasource ();
}
}
DataSource notes:
Package com.yryz.qshop.modules.dynamiclink.inter;
Import Java.lang.annotation.ElementType;
Import java.lang.annotation.Retention;
Import Java.lang.annotation.RetentionPolicy;
Import Java.lang.annotation.Target;
@Target ({Elementtype.type,elementtype.method})
@Retention (Retentionpolicy.runtime)
Public @interface DataSource {
String value ();
}
Interception device
Datasourceaspect.java
Package com.yryz.qshop.modules.dynamiclink.aspect;
Import Java.lang.reflect.Method;
Import Org.aspectj.lang.JoinPoint;
Import Org.aspectj.lang.reflect.MethodSignature;
Import Com.yryz.qshop.modules.dynamiclink.DynamicDataSourceHolder;
Import Com.yryz.qshop.modules.dynamiclink.inter.DataSource;
public class Datasourceaspect {
/**
* Intercepts the target method, gets the data source identity specified by @datasource, sets it to the thread store to switch the data source
*
* @param point
* @throws Exception
*/
P ublic void Intercept (Joinpoint point) throws Exception {
Class<?> target = Point.gettarget (). GetClass ();
Methodsignature signature = (methodsignature) point.getsignature ();
//Use annotations of the target type by default, and if not, use the annotations that implement the interface
for (class<?> clazz:target.getInterfaces ()) {
Resolvedatasource ( Clazz, Signature.getmethod ());
}
Resolvedatasource (target, Signature.getmethod ());
}
/**
* Extraction of target object method annotations and data source identification in type annotations
*
* @param clazz
* @param method
*/
private void Resolvedatasource (Class<?> clazz, method) {
try {
class<?>[] types = Method.getparametertypes ();
Default usage type annotations
if (Clazz.isannotationpresent (Datasource.class)) {
DataSource Source = clazz.getannotation (Datasource.class);
Dynamicdatasourceholder.setdatasource (Source.value ());
}
Method annotations can override type annotations
Method m = Clazz.getmethod (Method.getname (), types);
if (m! = null && m.isannotationpresent (Datasource.class)) {
DataSource Source = m.getannotation (Datasource.class);
Dynamicdatasourceholder.setdatasource (Source.value ());
}
} catch (Exception e) {
System.out.println (Clazz + ":" + e.getmessage ());
}
}
}
Spring configures multiple data sources (case)