Baru -baru ini, saya melakukan optimasi kueri keseimbangan margin. Ketika proyek dimulai, keseimbangan perlu dimuat sepenuhnya ke dalam cache lokal, karena keseimbangan margin semua pengendara harus ditanya sepenuhnya. Agar tidak mempengaruhi kinerja database utama, pertimbangkan untuk meninggalkan kueri. Jadi itu melibatkan kebutuhan untuk mengonfigurasi beberapa sumber data dalam suatu proyek dan dapat beralih secara dinamis. Setelah beberapa eksplorasi, switching dinamis direalisasikan dengan sempurna, dan metode konfigurasi dicatat untuk referensi Anda.
Ide desain keseluruhan
Metode Spring-Boot+AOP mewujudkan switching sumber multi-data, mewarisi AbstractroutingDataSource untuk mencapai akuisisi sumber data dinamis, dan menentukan sumber data menggunakan anotasi di lapisan layanan.
melangkah
1. Konfigurasi Sumber Multi-Data
Di application.properties, konfigurasi kami seperti ini
Sumber data #Master druid.master.url = jdbc: mysql: // url/masterdb? useunicode = true & characterencoding = utf8 & zerodateTimebehavior = converttonulldruid.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 = pilih 1#dari sumber data druid.slave.url = jdbc: mysql: // url/slavedb? useunicode = true & characterencoding = utf8 & zerodateTimebehavior = converttonulldruid.slave.username = xxxdruid.slave.password = 123druid id.slave.driver-class-name = com.mysql.jdbc.driverdruid.slave.max-wait = 5000druid.slave.max-active = 100druid.slave.test-on-borrow = truedruid.slave.validation-Query = pilih 1
Baca konfigurasi
<!-Master Data Source-> <bean primary = "true" id = "masterdb" init-method = "init" dash-method = "tutup"> <!-properti dasar url, pengguna, kata sandi-> <nama properti = "driverclassname" value = "com.mysql.jdbc.driver"/<name properten = "com.mysql.jdbc.driver"/<properti name = "" name = "" $ "name =" $ "$" ne property "name =" $ "name =" $ "name =" $ "$" name = "$" $ "name =" $ "ne property." name = "nama pengguna" value = "$ {druid.master.userName}"/> <name properti = "kata sandi" value = "$ {druid.master.password}"/> <!-Konfigurasikan inisialisasi maksimum-> <name properti = "maxactive" value = "$ {druid.master. name = "maxwait" value = "$ {druid.master.max-wait}"/> <name properti = "validationQuery" value = "$ {druid.master.validation-query}"/> <name properti = "testonborrow" value = "$ {druid.master.test-on --borrow}"-"}" {$ {$ {druid.master.test-on --test} "-" $ " id = "slavedb" init-method = "init" dash-method = "close"> <!-properti dasar url, pengguna, kata sandi-> <nama properti = "driverclassname" value = "com.mysql.jdbc.driver"/> <nama properti = "url" value = "$ {druid.slave.url} <nama nama =" "$" value = "$ {druid.slave.userName}"/> <name properti = "kata sandi" value = "$ {druid.slave.password}"/> <!-Konfigurasikan ukuran inisialisasi, minimum, dan maksimum-> <nama properti = "maxactive" value = "$ {druid.slave.max-active-Active =" MaxActive "value =" $ {druid.slave.max-active " <nama properti = "maxwait" value = "$ {druid.slave.max-wait}"/> <name properti = "validationquery" value = "$ {druid.slave.validation-query}"/> <Data Properti = "TestonBorrow" value = "$ {druid.slave.test.test-On-Oncoic" Sumber untuk didasarkan pada anotasi pada antarmuka layanan-> <bean id = "DataSource"> <nama properti = "targetDataSources"> <peta key-type = "java.lang.string"> <entry tey = "slave" value-ref = "slave"/<entry tey = "master" value-ref = "masterdb"/peta/peta/</entry key = "master" value-ref = "masterdb"/peta/peta </entry key = "master" value-ref = "masterdb"/peta/peta </map </withy = "master" value-ref = "masterdb"/pap Name = "DefaultTargetDataSource" Ref = "MasterDb"/> </tact> <!-Spring Jdbctemplate-> <bean id = "jdbctemplate"> <nama properti = "DataSource" Ref = "DataSource"/</bean> <!-Spring Transaction Manager-> <"UUKS =" Ref = "DataSource"/> </bean> <bean id = "TransactionTemplate"> <name properti = "transactionManager" ref = "transactionManager"/> </ bean> <tx: annotation-driven transaction-manager = "transactionManager" proxy-target-class-class = "true" order = "2"/2 "/2"/<porexbersqt "proxy-target-classor =" true "order =" 2 "/2"/2 "//transactionagager" proxy-target-class = "true" order = "2"/2 " id = "sqlSessionFactory"> <name properti = "DataSource" ref = "DataSource"/> <name properti = "mapperlocations" value = "classpath*: mapper-xxdb/*mapper*.xml"/> </ bean> <bean> <properti nama = "basepage" value = "value =" value = "nilai xx. name = "sqlSessionFactoryBeanName" value = "sqlSessionFactory"/> </t bean>2. Sumber Data Dinamis
Spring memberi kami AbstractroutingDataSource, sumber data dengan perutean. Setelah diwarisi, kita perlu mengimplementasikan determinecurrentlookupkey (), yang digunakan untuk menyesuaikan metode perutean nama sumber data aktual. Karena kami menyimpan informasi ke Threadlocal, kami hanya perlu mengeluarkannya.
Public Class DynamicDataSource memperluas AbstractroutingDataSource {private Logger Logger = LoggerFactory.getLogger (this.getClass ()); @Override Protected Object DetectionecurrentLookUpkey () {String DataSource = JDBCContExTholder.GetDataSource (); logger.info ("Sumber data adalah {}", DataSource); Return DataSource; }}3. Kelas switching dinamis sumber data
Peralihan sumber data dinamis didasarkan pada AOP, jadi kita perlu mendeklarasikan bagian AOP dan melakukan switching sumber data di depan bagian. Setelah bagian selesai, nama sumber data dihapus.
@Aspek @order (1) // Atur urutan eksekusi AOP (perlu sebelum transaksi, jika tidak transaksi hanya akan terjadi di pustaka default) @ComponentPublic Class DataSourCeaspect {private Logger Logger = LoggerFactory.getLogger (this.getClass ()); // potong titik @pointcut ("Eksekusi (*com.xxx.service.*.*(..))") public void aspek () {} @before ("aspek ()") void pribadi sebelumnya (titik gabung) {objek target = point.getTarget (); Metode String = point.getSignature (). GetName (); Class <?> Classz = target.getClass (); // Dapatkan kelas target kelas <?> [] ParameTerTypes = ((Methodyignature) point.getSignature ()) .getMethod (). GetParameterTypes (); coba {metode m = classz.getMethod (metode, parameterTypes); if (m! = null && m.isAnnotationPresent (myDataSource.class)) {myDataSource data = m.getannotation (mydataSource.class); logger.info ("Metode: {}, DataSource: {}", m.getName (), data.value (). getName ()); Jdbccontextholder.putDataSource (data.value (). GetName ()); // Masukkan sumber data di utas saat ini}} catch (Exception e) {logger.error ("Dapatkan kesalahan data data", e); // master jdbccontextholder.putDataSource (DataSourCetype.master.getName ()); // Masukkan sumber data di utas saat ini} @afterreturning ("aspek ()") batal public after (point joinpoint) {jdbccontextholder.cleardataSource (); }}4. Kategori Manajemen Sumber Data
kelas publik jdbccontextholder {private final static threadlocal <string> local = new threadlocal <> (); public static void putDataSource (nama string) {local.set (name); } public static string getDataSource () {return local.get (); } public static void clearasource () {local.remove (); }}5. Anotasi dan enumerasi sumber data
Ketika kami mengganti sumber data, kami umumnya mengimplementasikannya sebelum memanggil metode antarmuka tertentu, jadi kami mendefinisikan anotasi metode. Ketika AOP mendeteksi bahwa anotasi hadir pada metode ini, ia beralih sesuai dengan nama yang sesuai dengan nilai dalam anotasi.
@Retention (retentionpolicy.runtime) @target (elementType.method) public @interface myDataSource {value DataSourCetype ();} public enum DataSourCetype {// master ("master"), // slave ("slave"); nama string pribadi; private DataSourCetype (nama string) {this.name = name; } public string getName () {return name; } public void setName (name string) {this.name = name; }}6. Anotasi titik potong
Karena sumber data dinamis kami memiliki pustaka default, jika metode ini mengoperasikan pustaka default, tidak ada kebutuhan untuk anotasi. Jika Anda ingin mengoperasikan sumber data non-default, kami perlu menambahkan @MyDataSource ("DataSource Name") anotasi ke metode ini, sehingga Anda dapat menggunakan AOP untuk mencapai switching dinamis.
@ComponentPublic Class XXXSERVICEIMPL {@Resource Private XXXMapPerext XXXMapperExT; @MyDataSource (value = DataSourCetype.slave) Daftar Publik <POMPERTS> getAll () {return xxxmapperext.getAll (); }}Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.