Я написал блог «Spring+Mybatis+MySQL для создания распределенной структуры доступа к базе данных», прежде чем описать, как получить доступ к нескольким базам данных через динамические источники данных Mybatis. Тем не менее, предыдущее решение имеет некоторые ограничения (также описанные в оригинальном блоге): оно относится только к ситуациям, когда количество баз данных мало и фиксировано. Нечего делать с ситуацией, когда динамика базы данных увеличивается.
Схема, упомянутая ниже, может поддерживать динамическое добавление и удаление базы данных, а число не ограничено.
Подготовка среды базы данных
Вот пример MySQL, сначала постройте 3 базы данных локально для тестирования. Следует отметить, что это решение не ограничивает количество баз данных и поддерживает развертывание различных баз данных на разных серверах. Как показано на рисунке, db_project_001, db_project_002, db_project_003.
Создайте проект MicroService Java Backend
Создайте проект Spring Boot Maven:
Конфигурация: класс управления конфигурацией источника данных.
DataSource: логика управления источником данных, реализованная сама по себе.
DBMGR: Управляет взаимосвязью отображения между кодированием проекта и IP и именем базы данных (эта часть данных в фактическом проекте хранится в кэше Redis и может быть добавлена и удалена динамически).
Mapper: интерфейс доступа к базе данных.
Модель: отображение модели.
REST: RESTFUL Interface, выпущенный микросервисами снаружи, используемый здесь для тестирования.
Application.yml: настроить параметры JDBC базы данных.
Подробная реализация кода
1. Добавить конфигурацию источника данных
пакет com.elon.dds.config; import javax.sql.datasource; import org.apache.ibatis.session.sqlsessionFactory; импорт org.mybatis.spring.sqlsessionFactoryBean; импорт org.mybatis.spring.annatation.mapperscan; org.springframework.beans.factory.annotation.qualifier; импорт org.springframework.boot.autoconfigure.jdbc.datasourcebuilder; импорт org.springframework.boot.context.properties.configurationes; Импорт org.springframework.context.annotation.bean; Импорт org.springframework.context.annotation.configuration; Import com.elon.dds.datasource.dynamicdatasource;/*** Управление конфигурацией источника данных. * * @author elon * @version 26 февраля 2018 г. * / @configuration @mapperscan (basepackages = "com.elon.dds.mapper", value = "sqlSessionFactory") открытый класс DataSourceConfig { /** * Создание источника данных на основе параметров конфигурации. Используйте производные подклассы. * * @return Data Source */ @bean (name = "dataSource") @ConfigurationProperties (prefix = "spring.datasource") public DataSource getDataSource () {dataSourceBuilder builder = dataSourceBuilder.create (); Builder.Type (DynamicDataSource.class); return Builder.build (); } /*** Создать сеанс. * * @param dataSource Data source* @return Session Factory*/ @Bean(name="sqlSessionFactory") public SqlSessionFactory getSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource (DataSource); try {return bean.getObject (); } catch (Exception e) {e.printstackTrace (); вернуть ноль; }}} 2. Определите динамические источники данных
1) Сначала добавьте класс идентификации базы данных, чтобы отличить различные доступ к базе данных.
Поскольку мы создали отдельные базы данных для различных проектов, мы использовали кодирование проекта в качестве индекса базы данных. Микросервисы поддерживают многопоточную параллелизм и используют переменные потока.
пакет com.elon.dds.datasource;/*** Класс управления идентификацией базы данных. Используется для различения различных баз данных, подключенных к источникам данных. * * @author elon * @version 2018-02-25 */public class dbidentifier {/** * Используйте разные кодировки проекта для различения баз данных */private Static Threadlocal <string> ProjectCode = new Threadlocal <string> (); public Static String getProjectCode () {return ProjectCode.get (); } public static void setProjectCode (String Code) {projectCode.set (code); }}2) DynamicDataSource получен из DataSource, где реализовано динамическое переключение подключений к базе данных
Импорт java.lang.reflect.field; import java.sql.connection; импорт java.sql.sqlexception; import org.apache.logging.log4j.logmanager; импорт org.apache.logging.log4j.logger; импорт org.apache.tomcat.jdbc.pool.datas org.apache.tomcat.jdbc.pool.poolproperties; import com.elon.dds.dbmgr.projectdbmgr;/*** Определить динамический источник данных. Получен из базового источника данных, динамически реализованный сам по себе. * * @author elon * @version 2018-02-25 */public Class DynamicDataSource Extends DataSource {Private Static Logger log = logmanager.getLogger (dynamicDatasource.class); /*** Этот метод должен подключаться к различным базам данных при запросе данных из разных проектов. */ @Override Public Connection getConnection () {String ProjectCode = dbidentifier.getProjectCode (); // 1. Получить источник данных DATASOURCE DDS = DDSHOLDER.INSTANCE (). GETDDS (ProjectCode); // 2. Создать if (dds == null) {try {dataSource newdds = initdds (projectCode); Ddsholder.instance (). AddDds (ProjectCode, Newdds); } catch (allogalargumentException | allogalaccessexception e) {log.error ("Источник данных init Data. Fail. Код Project:" + ProjectCode); вернуть ноль; }} dds = ddsholder.instance (). getDDS (ProjectCode); try {return dds.getConnection (); } catch (sqlexception e) {e.printstacktrace (); вернуть ноль; }} /*** Скопируйте копию с текущим объектом данных в качестве шаблона. * * @return dds * @throws allogalaccessexception * @throws allogalargumentexception */ private dataSource initdds (String ProjectCode) Throws OldalArgumentException, allogalAccessException {dataSource dds = new DataSource (); // 2. Скопировать свойства PoolConfiguration PoolProperties Property = new PoolProperties (); Field [] pfields = poolproperties.class.getDeclaredFields (); Для (Поле F: Pfields) {f.setAccessible (true); Значение объекта = f.get (this.getPoolProperties ()); try {f.set (свойство, значение); } catch (Exception e) {log.Info ("Установить значение Fail. ATTR name:" + f.getName ()); продолжать; }} dds.setPoolProperties (Property); // 3. Установите имя базы данных и IP (как правило, порт, имя пользователя и пароль исправлены) String urlFormat = this.getUrl (); String url = string.format (urlformat, projectdbmgr.instance (). GetDbip (projectCode), projectDbmgr.instance (). GetDbname (projectCode)); dds.seturl (url); вернуть DDS; }}3) Управляйте высвобождением соединения данных через DDStimer (выброс неиспользованных источников данных, которые превысили указанное время)
пакет com.elon.dds.datasource; import org.apache.tomcat.jdbc.pool.datasource;/*** Динамическое управление временем источника данных. Подключение к базе данных, которое не имеет доступа в течение долгого времени, закрыто. * * @author elon * @version 25 февраля 2018 г. * /открытый класс ddstimer { /** * Период простоя. Подключения к базе данных, которые не были доступны в течение большего времени, будут выпущены. По умолчанию 10 минут. */ private static long idleperiodtime = 10 * 60 * 1000; / *** Динамический источник данных*/ private DataSource DDS; / *** Последнее время доступа*/ private long lastUsetime; public ddstimer (dataSource dds) {this.dds = dds; this.lastusetime = system.currenttimemilsis (); } / *** Обновлено последнее время доступа* / public void refreshtime () {lastuSetime = System.currentTimeMillis (); } /*** Обнаружение того, закрыто ли соединение данных из -за тайм -аута. * * @return True - Timeed Out; false - не истешен*/ public boolean checkandclose () {if (system.currenttimemillis () - lastusteTime> iDleperioDtime) {dds.Close (); вернуть истину; } вернуть false; } public DataSource getDDS () {return dds; }}4) Добавить DDSholder для управления различными источниками данных и предоставления функций добавления источника данных и запросов
пакет com.elon.dds.datasource; import java.util.hashmap; import java.util.iterator; импорт java.util.map; import java.util.map.entry; импорт java.util.timer; импорт org.apache.tomcat.jdbc.pool.datasource;/****** * * @author elon * @version 25 февраля 2018 г. * /public class ddsholder { /** * Управление динамическим списком источников данных. <Кодирование проекта, источник данных> */ private map <string, ddstimer> ddsmap = new hashmap <string, ddstimer> (); / *** Периодически очищать неиспользованные источники данных с помощью временных задач*/ частный статический таймер clearidletask = new Timer (); static {clearidletask.schedule (new clearidletimertask (), 5000, 60 * 1000); }; private ddsholder () {} /** Получить объект Singleton* / public static ddsholder ancess () {return ddsholderbuilder.instance; } /*** Добавить динамический источник данных. * * @param ProjectCode Кодирование * @param dds dds */ public synchronized void adddds (String ProjectCode, DataSource DDS) {ddStimer ddst = new DdStimer (DDS); ddsmap.put (ProjectCode, DDST); } / *** Запрос динамического источника данных** @param ProjectCode Кодирование* @return dds* / public Synchronized DataSource getDDS (String ProjectCode) {if (ddsmap.containskey (projectCode)) {ddstimer ddst = ddsmap.get (projectcode); ddst.refreshtime (); return ddst.getdds (); } return null; } /*** Очистить источники данных, которые были рассчитаны без кого -либо. */ public synchronized void cleariddedds () {iterator <inpit <string, ddstimer >> iter = ddsmap.entryset (). iterator (); for (; iter.hasnext ();) {inpit <string, ddstimer> entry = iter.next (); if (entry.getValue (). CheckAndClose ()) {iter.remove (); }}} / *** Класс Artifact Singleton* @author elon* @version 26 февраля 2018 г.* / Private Static Class ddsholderbuilder {Private Static DdSholder Extance = new DdSholder (); }}5) Задача таймера ClearIdletImerTask используется для регулярного очистки источников данных.
пакет com.elon.dds.datasource; import java.util.timertask;/*** Прозрачные задачи соединения. * * @author elon * @version 26 февраля 2018 г. */public class clearidletimertask расширяет timertask {@override public void run () {ddsholder.instance (). clearIdDds (); }}3. Управление кодированием кодирования проекта с IP и именем базы данных
пакет com.elon.dds.dbmgr; import java.util.hashmap; импорт java.util.map;/*** Управление базой данных проекта. Предоставляет интерфейс для имени базы данных запроса и IP на основе кодирования проекта. * @author elon* @version 25 февраля 2018 г.* /project projectdbmgr { /*** Сохранить отношения между кодированием проекта и именем данных. Вот жесткий код. В реальной разработке эти реляционные данные могут быть сохранены в кэше Redis; * Добавление нового проекта или удаление проекта требует только обновления кэша. В то время интерфейс этого класса должен быть изменен только для получения данных из кэша. */ private map <string, string> dbnamemap = new hashmap <string, string> (); /*** Сохранить отношения отображения между кодированием проекта и IP базы данных. */ private map <string, string> dbipmap = new hashmap <string, string> (); private projectdbmgr () {dbnamemap.put ("project_001", "db_project_001"); dbnamemap.put ("project_002", "db_project_002"); dbnamemap.put ("project_003", "db_project_003"); dbipmap.put ("project_001", "127.0.0.1"); dbipmap.put ("project_002", "127.0.0.1"); dbipmap.put ("project_003", "127.0.0.1"); } public Static ProjectDbmgr Encance () {return projectdbmgrbuilder.instance; } // В фактической разработке он изменен для получения публичной строки getDbname (String ProjectCode) {if (dbnamemap.containskey (projectCode)) {return dbnamemap.get (projectCode); } возвращаться ""; } // В фактической разработке мы изменяемся, чтобы получить публичную строку getDbip (string projectcode) {if (dbipmap.containskey (projectcode)) {return dbipmap.get (projectcode); } возвращаться ""; } private Static Class ProjectDbmgrBuilder {Private Static ProjectDbmgr Encance = new ProjectDbmgr (); }} 4. Определите Mapper для доступа к базе данных
пакет com.elon.dds.mapper; import java.util.list; import org.apache.ibatis.annotations.mapper; import org.apache.ibatis.annotation.result; импорт org.apache.ibatis.annotations.Results; импорт org.Apache.Annotation. Определение интерфейса mybatis отображения. ** @author elon* @version 26 февраля 2018 г.*/ @mapperpublic interface usermapper {/*** Запрос всех пользовательских данных* @return пользовательских данных*/@Results (value = @Result (Property = "userId", Column = "ID"), @Result (Property = name ", Column ="), @Result (@ReSult ")" are ")" are ")") ")") ")"), "are -name ="), "are"), "are -year"), "AgeResult"), "Earsult"), "Earsult"), "Earsult"), "Earsult"), "Earsult"). @Select ("Выберите идентификатор, имя, возраст от tbl_user") list <user> getUsers ();} 5. Определите модель объекта запроса
пакет com.elon.dds.model; public class user {private int userid = -1; частная строка name = ""; частный int age = -1; @Override public String toString () {return "name:" + name + "| возраст:" + age; } public int getUserid () {return userId; } public void setUserId (int userId) {this.Userid = userId; } public String getName () {return name; } public void setName (string name) {this.name = name; } public int getage () {return Age; } public void setage (int age) {this.age = age; }} 6. Определите интерфейс Restful для запроса пользовательских данных
пакет com.elon.dds.rest; import java.util.list; import org.springframework.beans.factory.annotation.autowired; import org.springframework.web.bindtation.requestmapping; импорт org.springframework.web.bindtation.requestmapping; org.springframework.web.bind.annotation.requestparam; import org.springframework.web.bind.annotation.restcontroller; импорт com.elon.dds.datasource.dbidentifier; импорт com.elon.dds.mapper.usermapper; импорт com.elon.dds.model. интерфейс. * * @author elon * @version 26 февраля 2018 г. */ @restcontroller @requestmapping (value = "/user") открытый класс wsuser {@autowired private usermapper usermapper; /*** Запрос всех пользовательских информации в проекте** @param ProjectCode Кодирование* @return пользовательских списков*/@requestmapping (value = "/v1/users", method = requestmethod.get) projectcode <user> QueryUser (@RequestParam (value = "projectCode", trey = true) stringCode) {dbidentifier.setcode); вернуть usermapper.getusers (); }}Требуется, чтобы параметр ProjectCode был включен в каждый запрос.
7. Напишите код запуска для приложения Spring Boot
пакет com.elon.dds; импорт org.springframework.boot.springapplication; импорт org.springframework.boot.autoconfigure.springbootapplication;/*** Привет, мир! * */@SpringBootApplicationPublic Class App {public static void main (string [] args) {System.out.println ("Hello World!"); SpringApplication.run (app.class, args); }} 8. Настройте источник данных в Application.yml
IP и имя базы данных базы данных используются с %s. Динамически переключите запрос пользовательских данных.
Весна: DataSource: URL: JDBC: MySQL: //%s: 3306/%s? useUnicode = true & haremencoding = UTF-8 имени пользователя: root Пароль: Compass-name: com.mysql.jdbc.driverlogging: config: classpath: log4j2.xml.
План испытания
1. Запрос данных Project_001 и нормально возврат
2. Запрос данных Project_002 и нормально возвращает
Суммировать
Выше приведено код реализации для доступа к нескольким базам данных через динамические источники данных конфигурации Spring. Я надеюсь, что это будет полезно для всех. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит всем вовремя. Большое спасибо за вашу поддержку сайту wulin.com!