Recientemente, estoy haciendo optimización de consultas de balance de margen. Cuando comienza el proyecto, el equilibrio debe cargarse por completo en el caché local, porque el saldo de margen de todos los pasajeros debe ser consultado por completo. Para no afectar el rendimiento de la base de datos principal, considere dejar la consulta. Por lo tanto, implica la necesidad de configurar múltiples fuentes de datos en un proyecto y poder cambiar dinámicamente. Después de un poco de exploración, la conmutación dinámica se realiza perfectamente y el método de configuración se registra para su referencia.
Ideas de diseño generales
El método Spring-Boot+AOP realiza la conmutación de fuentes de datos múltiples, hereda el abstruco de la adquisición para lograr la adquisición dinámica de la fuente de datos y especifica fuentes de datos utilizando anotaciones en la capa de servicio.
paso
1. Configuración de fuente de datos múltiples
En Application.Properties, nuestra configuración es como esta
#Fuente de datos del maestro druid.master.url = jdbc: mysql: // url/masterdb? useUnicode = true & caracterSencoding = 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 = triedruid.master.validation-query = selectar 1#de la fuente de datos druid.slave.url = jdbc: mysql: // url/slavedb? useUnicode = true & caracterSencoding = utf8 & zeroDateTimeBehavior = converttonullldruid.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 = triedruid.slave.validation-query = selectar 1
Configuración de lectura
< name = "username" value = "$ {druid.master.username}"/> <propiedad name = "contraseña" value = "$ {druid.master.password}"/> <!-Configure la inicialización máxima-> <propiedad name = "maxactive" value = "$ {druid.master.max-active}"/> <!-Configure el tiempo para obtener el tiempo de espera de la interferencia- name = "maxwait" value = "$ {druid.master.max-wait}"/> <propiedad name = "validationQuery" value = "$ {druid.master.validation-Query}"/> <Property name = "testOnBorrow" value = "$ {druid.master.test-on-braw id = "SlaVedb" init-Method = "init" destruye-method = "cerrar"> <!-URL de propiedades básicas, user, contraseña-> <propiedad name = "controladorclassname" value = "com.mysql.jdbc.driver"/> <propiedad = "url" value = "$ {druid.slave.url}/> <name de la propiedad =" nombre de usuario "nombre" nombre " value = "$ {druid.slave.username}"/> <propiedad name = "contraseña" value = "$ {druid.slave.password}"/> <!-Configure el tamaño de inicialización, mínimo y máximo-> <name de propiedad = "maxactive" value = "$ {druid.slave.max-activo}/> <!-Configure el tiempo de tiempo para obtener el tiempo de espera para obtener el tiempo. name = "maxwait" value = "$ {druid.slave.max-wait}"/> <propiedad name = "validationQuery" value = "$ {druid.slave.validation-query}"/> <propiedad name = "testonborrow" value = "$ {druid.slave.test-on-be Las anotaciones en la interfaz de servicio-> <bean id = "dataSource"> <propiedad name = "targetDataSources"> <map key-type = "java.lang.string"> <entry key = "esclavo" valor-ref = "slavedb"/> <key de entrada = "maestro" valiente-ref = "masterdb"/> </map> </propiedad> <n. ref="masterdb"/></bean><!-- Spring JdbcTemplate --><bean id="jdbcTemplate"> <property name="dataSource" ref="dataSource" /></bean><!-- Spring Transaction Manager--><bean id="transactionManager"> <property name="dataSource" ref="dataSource" /></bean><bean id = "TransActionTemplate"> <Property Name = "TransActionManager" ref = "TransActionManager"/> </bean> <tx: Annotation Transaction-Manager = "TransActionManager" proxy-Target-Class = "True" Order = "2"/> <!-DepositDbsqlSessionFactory-> <bean id = "sqlsession"> <name de propiedad = "name =" dataurce " ref = "DataSource"/> <Property name = "mapperLocations" value = "classpath*: mapper-xxdb/*mapper*.xml"/> </ bean> <bean> <propiedad name = "basepackage" valor = "xxdb.mapper"/> <name de propiedad = "sqlSessionFactoryname" value = "sqlSession2. Fuente de datos dinámico
Spring nos proporciona AbstrutingDataSource, una fuente de datos con enrutamiento. Después de heredar, necesitamos implementar su DetermineCurrentLlookUpkey (), que se utiliza para personalizar el método de enrutamiento del nombre de origen de datos real. Como guardamos la información en ThreadLocal, solo tenemos que sacarla.
Public Class DynamicDataSource extiende AbstrutingDataSource {private logger logger = loggerFactory.getLogger (this.getClass ()); @Override Objeto protegido DetetInECRENTLOVEWUpKey () {String DataSource = JDBCContexTholder.getDataSource (); logger.info ("La fuente de datos es {}", DataSource); devolver datos de datos; }}3. Clase de conmutación dinámica de fuente de datos
La conmutación dinámica de la fuente de datos se basa en AOP, por lo que necesitamos declarar una sección de AOP y hacer la conmutación de la fuente de datos frente a la sección. Después de completar la sección, se elimina el nombre de la fuente de datos.
@Aspecto @orden (1) // Establezca el orden de ejecución de AOP (debe ser antes de la transacción, de lo contrario, la transacción solo ocurrirá en la biblioteca predeterminada) @ComponentPublic Class DataSourCeAspect {private logger logger = loggerFactory.getLogger (this.getClasssS ()); // Cut Point @PointCut ("Ejecution (*com.xxx.service.*.*(..))") public void aspecto () {} @bebore ("aspecto ()") privado void antes (punto de unión) {Object Target = Point.getTarget (); Method de cadena = Point.getSignature (). GetName (); Clase <?> Classz = target.getClass (); // Obtener la clase de destino Class <?> [] ParametertyPes = ((MethodeSignature) Point.getSignature ()) .getMethod (). GetParametertyPes (); intente {método m = classz.getMethod (método, parametertypes); if (m! = null && m.isannotationPresent (myDataSource.class)) {myDataSource data = m.getAnnotation (myDataSource.class); logger.info ("Método: {}, DataSource: {}", m.getName (), data.value (). getName ()); Jdbccontextholder.putDataSource (data.value (). GetName ()); // Ponga la fuente de datos en el subproceso actual}} Catch (Exception e) {logger.error ("Obtener el error de DataSource", e); // maestro jdbccontextholder.putDataSource (dataSourCetype.master.getName ()); // Ponga la fuente de datos en el hilo actual}} @AfterReturning ("aspecto ()") public void después (punto de unión) {JDBCCONTEXTHOLDER.CLEARDASOURCE (); }}4. Categoría de gestión de fuente de datos
clase pública JDBCCONTEXTHOLder {private final Static shreadlocal <string> local = new ThreadLocal <> (); public static void putDataSource (nombre de cadena) {local.set (nombre); } public static string getDataSource () {return local.get (); } public static void clearDataSource () {local.remove (); }}5. Annotaciones de fuente de datos y enumeraciones
Cuando cambiamos las fuentes de datos, generalmente lo implementamos antes de llamar al método de la interfaz específica, por lo que definimos una anotación del método. Cuando AOP detecta que la anotación está presente en el método, cambia de acuerdo con el nombre correspondiente al valor en la anotación.
@Retention (retentionPolicy.Runtime) @Target (elementType.method) public @interface myDataSource {dataSourCeType value ();} public enum dataSourCetype {// maestro ("maestro"), // esclavo ("esclavo"); nombre de cadena privada; privado dataSourCeType (nombre de cadena) {this.name = name; } public String getName () {nombre de retorno; } public void setName (nombre de cadena) {this.name = name; }}6. Anotación de puntos de corte
Dado que nuestra fuente de datos dinámico tiene una biblioteca predeterminada, si el método es operar la biblioteca predeterminada, no hay necesidad de anotaciones. Si desea operar una fuente de datos no default, necesitamos agregar @mydataSource ("DataSource Annotation al método, para que pueda usar AOP para lograr un cambio dinámico.
@ComponentPublic Class XXXServiceImpl {@Resource private xxxmappeRext xxxmappeRext; @MydataSource (value = dataSourCetype.slave) Lista pública <S Object> getAll () {return xxxmappeRext.getall (); }}Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.