เมื่อเร็ว ๆ นี้ฉันกำลังทำการเพิ่มประสิทธิภาพการสืบค้นยอดคงเหลือ เมื่อโครงการเริ่มต้นความสมดุลจะต้องโหลดอย่างเต็มที่ในแคชท้องถิ่นเนื่องจากความสมดุลของผู้ขับขี่ทุกคนจะต้องมีการสอบถามอย่างเต็มที่ เพื่อไม่ให้ส่งผลกระทบต่อประสิทธิภาพของฐานข้อมูลหลักให้พิจารณาออกจากแบบสอบถาม ดังนั้นจึงเกี่ยวข้องกับความจำเป็นในการกำหนดค่าแหล่งข้อมูลหลายแหล่งในโครงการและสามารถเปลี่ยนแบบไดนามิกได้ หลังจากการสำรวจบางครั้งการสลับแบบไดนามิกจะได้รับการยอมรับอย่างสมบูรณ์แบบและวิธีการกำหนดค่าจะถูกบันทึกไว้สำหรับการอ้างอิงของคุณ
แนวคิดการออกแบบโดยรวม
เมธอด Spring-Boot+AOP ตระหนักถึงการสลับแหล่งข้อมูลหลายข้อมูลสืบทอด AbstractroutingDataSource เพื่อให้ได้มาซึ่งการได้มาของแหล่งข้อมูลแบบไดนามิกและระบุแหล่งข้อมูลโดยใช้คำอธิบายประกอบที่ชั้นบริการ
ขั้นตอน
1. การกำหนดค่าแหล่งข้อมูลหลายข้อมูล
ใน application.properties การกำหนดค่าของเราเป็นเช่นนี้
#Master Data Source druid.master.url = jdbc: mysql: // url/masterdb? useunicode = true & characterencoding = utf8 & zerodateTimeBehavior = convertOnulldruid.master.username = xxxdruid.master.master. id.master.driver-class-name = com.mysql.jdbc.driverdruid.master.max-wait = 5000druid.master.max-active = 100druid.master.test-on-borm 1#จากแหล่งข้อมูล druid.slave.url = jdbc: mysql: // url/slavedb? useunicode = true & starentencoding = utf8 & zerodatetimebehavior = convertonulldruid.slave.username = xxxdruid.slave.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-query 1
อ่านการกำหนดค่า
<!-แหล่งข้อมูลต้นแบบ-> <Bean primary = "true" id = "MasterDb" init-method = "init" destroy-method = "close"> <!-URL คุณสมบัติพื้นฐานผู้ใช้รหัสผ่าน-> <property name = "driverclassName" value = "com.mysql.jdbc.driver"/> name = "username" value = "$ {druid.master.username}"/> <property name = "รหัสผ่าน" value = "$ {druid.master.master.password}"/> <! name = "maxwait" value = "$ {druid.master.max-wait}"/> <property name = "validationQuery" value = "$ {druid.master.validation-query}"/> <property name = "testonborrow" value = "$ {druid.master.test- primary = "true" id = "slavedb" init-method = "init" destroy-method = "close"> <!-URL คุณสมบัติพื้นฐานผู้ใช้รหัสผ่าน-> <property name = "driverclassName" value = "com.mysql.jdbc.driver"/> <property name = "url" value = "$ value = "$ {druid.slave.username}"/> <property name = "รหัสผ่าน" value = "$ {druid.slave.password}"/> <!-กำหนดค่าขนาดเริ่มต้นขั้นต่ำและสูงสุด-<nome = "maxactive" value = "$ {druid.slave.max-active name = "maxwait" value = "$ {druid.slave.max-wait}"/> <property name = "validationQuery" value = "$ {druid.slave.validation-query}"/> <property = "testonborrow" value = "$ {druid.slave.test เพื่อให้ได้ตามคำอธิบายประกอบบนอินเทอร์เฟซบริการ-> <bean id = "dataSource"> <property name = "targetDataSources"> <แผนที่ key-type = "java.lang.string"> <entry key = "Slave" Value-ref = "SlavedB"/> name = "defaulttargetDataSource" ref = "masterdb"/> </ebean> <!-สปริง jdbctemplate-> <bean id = "jdbctemplate"> <property name = "dataSource" ref = "DataSource"/> </ebean> <! /> </ebean> <bean id = "transactionTemplate"> <property name = "transactionManager" ref = "transactionManager"/> </ebean> <tx: transaction-driven transaction-manager = "TransactionManager" Proxy-target-class = "true" name = "dataSource" ref = "dataSource"/> <property name = "mapperlocations" value = "classpath*: mapper-xxdb/*mapper*.xml"/> </ebean> value = "SQLSessionFactory"/> </ebean>2. แหล่งข้อมูลแบบไดนามิก
ฤดูใบไม้ผลิให้เราด้วย abstractroutingDataSource แหล่งข้อมูลที่มีการกำหนดเส้นทาง หลังจากรับมรดกเราจำเป็นต้องใช้ decinecurrentlookupkey () ซึ่งใช้ในการปรับแต่งวิธีการกำหนดเส้นทางของชื่อแหล่งข้อมูลจริง เนื่องจากเราบันทึกข้อมูลลงใน ThreadLocal เราจึงต้องนำออกมา
Public Class DynamicDataSource ขยาย AbstractroutingDataSource {Private Logger logger = loggerFactory.getLogger (this.getClass ()); @Override วัตถุที่ได้รับการป้องกัน decinecurrentLookUpkey () {สตริง dataSource = jdbccontextholder.getDataSource (); logger.info ("แหล่งข้อมูลคือ {}", DataSource); ส่งคืนแหล่งข้อมูล; -3. คลาสการสลับแบบไดนามิกของแหล่งข้อมูล
การสลับแหล่งข้อมูลแบบไดนามิกขึ้นอยู่กับ AOP ดังนั้นเราจำเป็นต้องประกาศส่วน AOP และทำการสลับแหล่งข้อมูลที่ด้านหน้าของส่วน หลังจากที่ส่วนเสร็จสิ้นชื่อแหล่งข้อมูลจะถูกลบออก
@ASPACT @ORDER (1) // ตั้งค่าลำดับการดำเนินการของ AOP (จำเป็นต้องเป็นก่อนการทำธุรกรรมมิฉะนั้นการทำธุรกรรมจะเกิดขึ้นเฉพาะในไลบรารีเริ่มต้นเท่านั้น) @ComponentPublic คลาส DataSourceAspect {Private Logger Logger = LoggerFactory.getLogger (this.getClass ()); // Cut Point @PointCut ("Execution (*com.xxx.service.*.*(.. ))") Public Void แง่มุม () {} @Before ("Aspect ()") โมฆะส่วนตัวก่อน (จุดเข้าร่วม) {วัตถุเป้าหมาย = point.getTarget (); วิธีการสตริง = point.getSignature (). getName (); คลาส <s?> classz = target.getClass (); // รับคลาสคลาสเป้าหมาย <?> [] พารามิเตอร์ parameterTypes = ((methodSignature) point.getSignature ()) .getMethod (). getParameterTypes (); ลอง {method m = classz.getMethod (เมธอด, พารามิเตอร์ therypes); if (m! = null && m.isannotationpresent (myDataSource.class)) {myDataSource data = m.getAnnotation (myDataSource.class); logger.info ("วิธีการ: {}, dataSource: {}", m.getName (), data.value (). getName ()); jdbccontextholder.putDataSource (data.value (). getName ()); // ใส่แหล่งข้อมูลในเธรดปัจจุบัน}} catch (Exception e) {logger.error ("รับข้อผิดพลาดของแหล่งข้อมูล", e); // ต้นแบบ jdbccontextholder.putDataSource (dataSourcetype.master.getName ()); // วางแหล่งข้อมูลในเธรดปัจจุบัน}} @afterreturning ("แง่มุม ()") โมฆะสาธารณะ -4. หมวดหมู่การจัดการแหล่งข้อมูล
คลาสสาธารณะ JDBCCONTEXTHOLDER {Private Final Final Static ThreadLocal <String> local = new ThreadLocal <> (); โมฆะสาธารณะคงที่ putdataSource (ชื่อสตริง) {local.set (ชื่อ); } สตริงคงที่สาธารณะ getDataSource () {return local.get (); } โมฆะคงที่สาธารณะ cleardatasource () {local.remove (); -5. คำอธิบายประกอบของแหล่งข้อมูลและการแจกแจง
เมื่อเราสลับแหล่งข้อมูลเรามักจะนำไปใช้ก่อนที่จะเรียกวิธีการของอินเทอร์เฟซเฉพาะดังนั้นเราจึงกำหนดคำอธิบายประกอบวิธีการ เมื่อ AOP ตรวจพบว่ามีคำอธิบายประกอบอยู่ในวิธีการจะสลับตามชื่อที่สอดคล้องกับค่าในคำอธิบายประกอบ
@Retention (RetentionPolicy.Runtime) @Target (ElementType.Method) สาธารณะ @Interface myDataSource {ค่า dataSourcetype ();} public enum dataSourcetype {// master ("master"), // slave ("slave"); ชื่อสตริงส่วนตัว; DataSourcetype ส่วนตัว (ชื่อสตริง) {this.name = name; } สตริงสาธารณะ getName () {ชื่อคืน; } โมฆะสาธารณะ setName (ชื่อสตริง) {this.name = name; -6. คำอธิบายประกอบจุดตัด
เนื่องจากแหล่งข้อมูลแบบไดนามิกของเรามีไลบรารีเริ่มต้นหากวิธีการใช้งานไลบรารีเริ่มต้นจึงไม่จำเป็นต้องมีคำอธิบายประกอบ หากคุณต้องการใช้งานแหล่งข้อมูลที่ไม่ใช่ default เราจำเป็นต้องเพิ่ม @MyDataSource ("ชื่อแหล่งข้อมูล") คำอธิบายประกอบลงในวิธีการเพื่อให้คุณสามารถใช้ AOP เพื่อให้ได้การสลับแบบไดนามิก
@ComponentPublic คลาส XXXServiceImpl {@Resource ส่วนตัว XXXMAPPEREXT XXXMAPPEREXT; @MyDatAsource (value = dataSourCetype.slave) รายการสาธารณะ <Ojrop> getAll () {return xxxmapperext.getAll (); -ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น