1.新建dynamic-mybatis.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE  configuration  PUBLIC  "-//mybatis.org//DTD Config 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
  
    <settings>  
        <!--开启缓存-->
        <setting name="cacheEnabled" value="true"/>  
    </settings>  
  
    <typeAliases>  
        <!--配置实体包名-->
        <package name="com.xxx.model"/>  
    </typeAliases>  
  
    <plugins>  
        <!--配置分页插件-->
        <plugin interceptor="com.github.pagehelper.PageHelper">  
            <property name="reasonable" value="false" />  
        </plugin>  
    </plugins>  
  
 
    <environments default="development">  
        <environment id="development">  
            <transactionManager type="JDBC"/>  
            <dataSource type="POOLED">  
                <property name="driver" value="__driver__" />  
                <property name="url" value="__url__" />  
                <property name="username" value="__username__" />  
                <property name="password" value="__password__" />  
            </dataSource>  
        </environment>  
    </environments>  
  
    <mappers>  
        <mapper class="com.xxx.dao.LocationDao"/>  
        <mapper resource="com/xxx/mapping/LocationMapper.xml"/>  
        <mapper class="com.vss.dao.MileageDao"/>  
        <mapper resource="com/xxx/mapping/MileageMapper.xml"/>  
        <mapper class="com.xxx.dao.DataSourcePartitionDao"/>  
        <mapper resource="com/xxx/mapping/DataSorucePartitionMapper.xml"/>  
    </mappers>  
</configuration>
__driver____url____username____password__配置分别在代码中动态替换
  • 动态分库实现,Java代码

    @Component  
    public class DynamicDataSource {  
    
      /**  
     * 默认的数据源名  
    */  
    public static final String DEFAULT_LOOKUP_KEY = "0";  
    
      /**  
     * 默认的jdbc url  
     */  private static final String DEFAULT_JDBC_URL = "jdbc:mysql://%s:35200/vss?useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true";  
    
      private Map<String, MySQLNode> sessionMap = new ConcurrentHashMap<>();  
    
      @Autowired  
    private LocationDao locationDao;  
    
      @Autowired  
    private MileageDao mileageDao;  
    
      @Autowired  
    private DataSourcePartitionDao dataSourcePartitionDao;  
    
      public LocationDao getLocationDao(String nodeID){  
          if(StringUtils.isNull(nodeID) || DEFAULT_LOOKUP_KEY.equals(nodeID)){  
              return locationDao;  
          }  
    
          return getDao(nodeID, LocationDao.class);  
      }  
    
      public MileageDao getMileageDao(String nodeID){  
          if(StringUtils.isNull(nodeID) || DEFAULT_LOOKUP_KEY.equals(nodeID)){  
              return mileageDao;  
          }  
    
          return getDao(nodeID, MileageDao.class);  
      }  
    
      public DataSourcePartitionDao getDataSourcePartitionDao(String nodeID){  
          if(StringUtils.isNull(nodeID) || DEFAULT_LOOKUP_KEY.equals(nodeID)){  
              return dataSourcePartitionDao;  
          }  
    
          return getDao(nodeID, DataSourcePartitionDao.class);  
      }  
    
      public <T> T getDao(String nodeID, Class<T> clazz){  
          MySQLNode node = sessionMap.get(nodeID);  
          if(node == null){  
              node = getMySQLNode(nodeID);  
              sessionMap.put(nodeID, node);  
          }  
    
          if(node == null){  
              return null;  
          }  
          return node.getSqlSession().getMapper(clazz);  
      }  
    
      /**  
     * 获取一个MySQLNode  
     * @param nodeID  
    * @return  
    */  
    private MySQLNode getMySQLNode(String nodeID) {  
          Servernode server = AlarmLinkService.getServerNodeByID(nodeID);  
          if(server == null){  
              LogUtils.error("没有找到servernode nodeID=" + nodeID, new Throwable().getStackTrace(), null);  
              return null;  
          }  
          SqlSession session = getSqlSession(server.getNodeIp(), server.getDbUser(), server.getDbPwd());  
    
          if(session == null){  
              LogUtils.error("创建SqlSession失败 nodeID=" + nodeID,  null);  
              return null;  
          }  
    
          return createMySQLNode(nodeID, server.getNodeIp(), server.getDbUser(), server.getDbPwd(), session);  
      }  
    
      private SqlSession getSqlSession(String ip, String username, String password){  
          try {  
              InputStream in = DynamicDataSource.class.getClassLoader().getResourceAsStream("config/dynamic-mybatis.xml");  
              String configXml = IOUtils.toString(in, StandardCharsets.UTF_8);  
              String lastConfigXML = configXml.replace("__driver__", "com.mysql.jdbc.Driver")  
                      .replace("__url__", String.format(DEFAULT_JDBC_URL, ip))  
                      .replace("__username__", username)  
                      .replace("__password__", password);  
              InputStream inputStream = IOUtils.toInputStream(lastConfigXML, StandardCharsets.UTF_8.name());  
    
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()  
                      .build(inputStream);  
              SqlSession session = sqlSessionFactory.openSession(true);  
              return session;  
          }catch (Exception e){  
              LogUtils.error("创建SqlSession出现异常 ip=" + ip,  e);  
          }  
    
          return null;  
      }  
    
      /**  
     * 每个5秒钟刷新数据源是否发送改变  
    */  
    public void refreshDataSource() {  
          //1.检测是否有新增  
    for (Map.Entry<String, Servernode> entry : AlarmLinkService.gMapServernode().entrySet()) {  
              String dbNodeName = entry.getKey();  
              Servernode server = entry.getValue();  
              if (existServerNode(server) || DEFAULT_LOOKUP_KEY.equals(dbNodeName)) {  
                  continue;  
              }  
              SqlSession session = getSqlSession(server.getNodeIp(), server.getDbUser(), server.getDbPwd());  
              MySQLNode ds = createMySQLNode(server.getNodeGuid(), server.getNodeIp(), server.getDbUser(), server.getDbPwd(), session);  
              sessionMap.put(server.getNodeGuid(), ds);  
          }  
    
          //2.检测是否需要移除  
    checkTargetDataSources();  
      }  
    
      private boolean existServerNode(Servernode server){  
          if(sessionMap.isEmpty()){  
              return false;  
          }  
    
          for (Map.Entry<String, MySQLNode> entry : sessionMap.entrySet()) {  
              String nodeID = entry.getKey();  
              MySQLNode ds = entry.getValue();  
    
              String url = String.format(DEFAULT_JDBC_URL, server.getNodeIp());  
              if(org.apache.commons.lang3.StringUtils.equals(server.getNodeGuid(), nodeID)  
                      && org.apache.commons.lang3.StringUtils.equals(ds.getUrl(), url)  
                      && org.apache.commons.lang3.StringUtils.equals(ds.getUsername(), server.getDbUser())  
                      && org.apache.commons.lang3.StringUtils.equals(ds.getPassword(), server.getDbPwd())) {  
                  return true;  
              }  
          }  
          return false;  
      }  
    
      private boolean checkTargetDataSources(){  
          boolean rs = false;  
          try {  
              Iterator<String> dbNodeKeys = sessionMap.keySet().iterator();  
              while (dbNodeKeys.hasNext()) {  
                  String nodeID = dbNodeKeys.next();  
                  MySQLNode ds = sessionMap.get(nodeID);  
                  boolean exist = false;  
                  for (Map.Entry<String, Servernode> entry : AlarmLinkService.gMapServernode().entrySet()) {  
                      Servernode server = entry.getValue();  
                      String url = String.format(DEFAULT_JDBC_URL, server.getNodeIp());  
                      if (org.apache.commons.lang3.StringUtils.equals(server.getNodeGuid(), nodeID)  
                              && org.apache.commons.lang3.StringUtils.equals(ds.getUrl(), url)  
                              && org.apache.commons.lang3.StringUtils.equals(ds.getUsername(), server.getDbUser())  
                              && org.apache.commons.lang3.StringUtils.equals(ds.getPassword(), server.getDbPwd())) {  
                          exist = true;  
                          break;  
                      }  
                  }  
                  if (!exist) {  
                      trySessionClose(ds.getSqlSession());  
                      dbNodeKeys.remove();  
                      rs = true;  
                  }  
              }  
          }catch (Exception e){  
              LogUtils.error("执行checkTargetDataSources出现异常", e);  
          }  
          return rs;  
      }  
    
      private MySQLNode createMySQLNode(String nodeID, String ip, String username, String password, SqlSession session){  
          String url = String.format(DEFAULT_JDBC_URL, ip);  
          return new MySQLNode(nodeID, url, username, password, session);  
      }  
    
    //退出程序时销毁
      public void destroy(){  
          try {  
              for (Map.Entry<String, MySQLNode> entry : sessionMap.entrySet()) {  
                  trySessionClose(entry.getValue().getSqlSession());  
              }  
          }catch (Exception e){  
              LogUtils.error("销毁SqlSession出现异常",  e);  
          }  
      }  
    
      //当操作数据抛异常时,移除内容包出现“Communications link failure”调用close方法进行移除节点
      public void close(String nodeID){  
          MySQLNode mySQLNode = sessionMap.remove(nodeID);  
          if(mySQLNode != null) {  
              trySessionClose(mySQLNode.getSqlSession());  
          }  
      }  
    
      private void trySessionClose(SqlSession session){  
          try {  
              session.close();  
          }catch (Exception e){  
              LogUtils.error("执行SqlSession close出现异常", e);  
          }  
      }  
    }
最后修改:2022 年 09 月 03 日
如果觉得我的文章对你有用,请随意赞赏