Récemment, je fais l'optimisation des requêtes de balance des marges. Lorsque le projet commence, l'équilibre doit être pleinement chargé dans le cache local, car l'équilibre de la marge de tous les cyclistes doit être entièrement interrogé. Afin de ne pas affecter les performances de la base de données principale, envisagez de quitter la requête. Cela implique donc la nécessité de configurer plusieurs sources de données dans un projet et de pouvoir changer dynamiquement. Après une certaine exploration, la commutation dynamique est parfaitement réalisée et la méthode de configuration est enregistrée pour votre référence.
Idées de conception globales
La méthode Spring-Boot + AOP réalise la commutation de la source multi-données, hérite d'abstratroutingDataSource pour obtenir une acquisition dynamique des sources de données et spécifie des sources de données à l'aide d'annotations au niveau de la couche de service.
étape
1. Configuration de la source multi-données
Dans application.properties, notre configuration est comme ceci
Source de données #Master druid.master.url = jdbc: mysql: // url / masterdb? useunicode = true & worseencoding = utf8 & zerodatetimeBehavior = converttonllDruid.master.username = xxxdruid.master.password = 123DrU id.master.driver-Class-Name = com.mysql.jdbc.driverdruid.master.max-wait = 5000druid.master.max-active = 100druid.master.test-on-borrow = truedruid.master.validation-query = select 1 # de la source de données druid.slave.url = jdbc: mysql: // url / slavedb? useunicode = true & caractotcoding = utf8 & zerodatetimebehavior = converttonulldruid.slave.username = xxxdruid.slave.password = 123dru id.slave.driver-class-name = com.mysql.jdbc.driverdruid.slave.max-wait = 5000druid.slave.max-active = 100druid.slave.test-on-borrow = truedruid.slave.validation-Quey = select 1
Lire la configuration
<! - Master Data Source -> <bean primory = "true" id = "masterdb" init-méthod = "init" destrie-méthod = "close"> <! - Basic Properties URL, utilisateur, mot de passe -> <propriété name = "driverclassname" value = "com.mysql.jdbc.driver" /> <propriété name = "url" value = "$ {drud.master.url. name = "username" value = "$ {druid.master.username}" /> <propriété name = "mot de passe" value = "$ {druid.master.password}" /> <! - Configurez l'initialisation maximale -> <propriété name = "maxactive" value = "$ {duid.master.max-active}" /> <! name = "maxwait" value = "$ {druid.master.max-wait}" /> <propriété name = "validationquery" value = "$ {druid.master.validation-query}" /> <propriété name = "testonborrow" value = "{$ druid.master.test-borrow}" /> </ bean> <! id = "slavedb" init-méthod = "init" destrement-méthod = "close"> <! - Basic Properties URL, utilisateur, mot de passe -> <propriété name = "driverClassName" value = "com.mysql.jdbc.driver" /> <propriété name = "url" value = "$ {druid.slave.url}" /> <url name = "username" Value = "$ {druid.slave.username}" /> <propriété name = "mot de passe" value = "$ {druid.slave.password}" /> <! - Configurez la taille de l'initialisation, minimum et maximum -> <propriété name = "maxactive" value = "$ {duid.slave. name = "maxwait" value = "$ {druid.slave.max-wait}" /> <propriété name = "validationQuery" value = "$ {druid.slave.validation-query}" /> <propriété name = "testonBorrow" value = "$ {dynamic de la source de données de données pour geler}" /> </ bean> Basé sur les annotations sur l'interface de service -> <bean id = "dataSource"> <propriété name = "TargetDataSources"> <map key-type = "java.lang.string"> <entrée key = "slave" value-ref = "Slaveb" /> <preny key = "maître" value-ref = "masterdb" /> </map> name = "defaultTargetDataSource" ref = "Masterdb" /> </anEn> <! - Spring JdbCTemplate -> <bean id = "JDBCTemplate"> <propriété name = "DataSource" Ref = "DataSource" /> </ bean /> </ bean> <bean id = "TransactionTemplate"> <propriété name = "TransactionManager" ref = "TransactionManager" /> </ank> <tx: annotation-Drive Transaction-manager = "TransactionManager" Proxy-Target-Class = "True" Order = "2" /> <! - DéposedBsSessionFactor name = "dataSource" ref = "dataSource" /> <propriété name = "mappenlocations" value = "classPath *: mappe-xxdb / * mapper * .xml" /> </ bean> <any> <propriété name = "basepackage" value = "xxdb.mapper" /> <propriété name = "sqlSessionfactoryBeanname" Value = "SqlSessionFactory" /> </EAN>2. Source de données dynamique
Spring nous fournit AbstractroutingDataSource, une source de données avec routage. Après héritage, nous devons mettre en œuvre son déterminancecurrentlookupkey (), qui est utilisé pour personnaliser la méthode de routage du nom de la source de données réelle. Puisque nous enregistrons les informations sur ThreadLocal, nous avons juste besoin de les retirer.
La classe publique DynamicDataSource étend AbstratTroutingDataSource {private logger logger = loggerfactory.getLogger (this.getClass ()); @Override Protected Object DetermentCurrentLookUpkey () {String dataSource = jdbcConTexTholder.getDataSource (); Logger.info ("La source de données est {}", DataSource); return dataSource; }}3. Classe de commutation dynamique de source de données
La commutation de source de données dynamique est basée sur AOP, nous devons donc déclarer une section AOP et effectuer un commutateur de source de données devant la section. Une fois la section terminée, le nom de la source de données est supprimé.
@ Aspect @ ordre (1) // Définissez l'ordre d'exécution AOP (doit être avant la transaction, sinon la transaction ne se produira que dans la bibliothèque par défaut) @ComponentPublic Class dataSourCeSpect {private logger logger = loggerfactory.getLogger (this.getClass ()); // Cut Point @Pointcut ("EXECUTION (* com.xxx.service. *. * (..))") public void aspect () {} @before ("aspect ()") private void avant (point joinpoint) {objet Target = Point.getTarget (); String méthode = point.getSignature (). GetName (); Classe <?> Classz = cible.getClass (); // Obtenez la classe cible classe <?> [] ParameterTypes = ((Methodsignature) Point.getSignature ()) .getMethod (). GetParAmEterTypes (); try {Method m = classz.getMethod (méthode, parameterTypes); if (m! = null && m.isannotationPresent (mydatasource.class)) {MyDataSource data = m.getAnnotation (myDataSource.class); Logger.info ("Méthode: {}, DataSource: {}", m.getName (), data.value (). getName ()); Jdbccontextholder.putDataSource (data.value (). GetName ()); // mettez la source de données dans le thread actuel}} catch (exception e) {logger.error ("Get DataSource Error", e); // maître jdbccontextholder.putdatasource (dataSourceType.master.getName ()); // Mettez la source de données dans le thread actuel}} @afterreturning ("aspect ()") public void after (joinpoint point) {jdbcConTexTholder.ClearDatasource (); }}4. catégorie de gestion des sources de données
classe publique jdbccontexTholder {private final static threadLocal <string> local = new ThreadLocal <> (); public static void putDataSource (nom de chaîne) {local.set (name); } String statique public getDataSource () {return local.get (); } public static void clearDataSource () {local.remove (); }}5. Annotations et énumérations de la source de données
Lorsque nous changeons de sources de données, nous les implémentons généralement avant d'appeler la méthode de l'interface spécifique, nous définissons donc une annotation de méthode. Lorsque AOP détecte que l'annotation est présente sur la méthode, elle change en fonction du nom correspondant à la valeur de l'annotation.
@Retention (RetentionPolicy.Runtime) @target (elementType.Method) public @Interface MyDataSource {DataSourCeType Value ();} public Enum dataSourceType {// Master ("Master"), // Slave ("Slave"); nom de chaîne privé; private dataSourCetype (name de chaîne) {this.name = name; } public String getName () {Nom de retour; } public void setName (string name) {this.name = name; }}6. Annotation du point de coupe
Étant donné que notre source de données dynamique dispose d'une bibliothèque par défaut, si la méthode consiste à utiliser la bibliothèque par défaut, il n'y a pas besoin d'annotations. Si vous souhaitez utiliser une source de données non défaut, nous devons ajouter une annotation @MyDataSource ("DataSource Name") à la méthode, afin que vous puissiez utiliser AOP pour réaliser une commutation dynamique.
@ComponentPublic classe XXXServiceIMPl {@Resource private xxxmapperext xxxmapperext; @Mydatasource (value = dataSourCetype.slave) public list <objet> getall () {return xxxmapperext.getall (); }}Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.