Mybatis+ MySQL5.7主从数据库复制配置

 

实现基本的mysql主数据写入,从数据库查询,从数据库简单负载均衡(均匀分配请求数)

 

1.1配置两个数据源参数

jdbc.master.type=mysql

jdbc.master.driverClassName=com.mysql.jdbc.Driver

jdbc.master.url=jdbc:mysql://192.168.113.11:3306/showbox?useUnicode=true&characterEncoding=utf-8

jdbc.master.username=root

jdbc.master.password=zhd123456

 

jdbc.slave1.type=mysql

jdbc.slave1.driverClassName=com.mysql.jdbc.Driver

jdbc.slave1.url=jdbc:mysql://192.168.113.200:3306/showbox?useUnicode=true&characterEncoding=utf-8

jdbc.slave1.username=root

jdbc.slave1.password=zhd123456

1.2 配置applicationContext-datasource.xml

          

   

   

   

          

          

          

          

          

          

          

          

          

          

          

          

          

          

 

          

   

   

   

          

          

          

          

          

          

          

          

          

          

          

          

          

          

 

   

       

       

           

               

           

       

   

          

          

 

 

1.3配置applicationContext-datasource.xml

          

          

          

          

                   

                             classpath:/META-INF/mybatis/mybatis-pager.xml

                             classpath*:com/flame/dao/mapper/*.xml 

                             classpath*:com/flame/dao/custom/*.xml  

                   

          

1.4DynamicDataSource 动态切换数据源代码

package com.flame.common.dataSource;

 

import java.util.HashMap;

import java.util.LinkedList;

import java.util.List;

import java.util.Map;

import java.util.concurrent.atomic.AtomicLong;

 

import javax.sql.DataSource;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

 

public class DynamicDataSource extends AbstractRoutingDataSource {

         private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDataSource.class);

 

         private DataSource master; // 主库,只允许有一个

         private List slaves; // 从库,允许有多个

         private AtomicLong slaveCount = new AtomicLong();

         private int slaveSize = 0;

 

         private Map dataSources = new HashMap();

 

         private static final String DEFAULT = "master";

         private static final String SLAVE = "slave";

 

         private static final ThreadLocal> datasourceHolder = new ThreadLocal>() {

 

                   @Override

                   protected LinkedList initialValue() {

                            return new LinkedList();

                   }

 

         };

 

         /**

          * 初始化

          */

         @Override

         public void afterPropertiesSet() {

                   if (null == master) {

                            throw new IllegalArgumentException("Property 'master' is required");

                   }

                   dataSources.put(DEFAULT, master);

                   if (null != slaves && slaves.size() > 0) {

                            for (int i = 0; i < slaves.size(); i++) {

                                     dataSources.put(SLAVE + (i + 1), slaves.get(i));

                            }

                            slaveSize = slaves.size();

                   }

                   this.setDefaultTargetDataSource(master);

                   this.setTargetDataSources(dataSources);

                   super.afterPropertiesSet();

         }

 

         /**

          * 选择使用主库,并把选择放到当前ThreadLocal的栈顶

          */

         public static void useMaster() {

                   if (LOGGER.isDebugEnabled()) {

                            LOGGER.debug("use datasource :" + datasourceHolder.get());

                   }

                   LinkedList m = datasourceHolder.get();

                   m.offerFirst(DEFAULT);

         }

 

         /**

          * 选择使用从库,并把选择放到当前ThreadLocal的栈顶

          */

         public static void useSlave() {

                   if (LOGGER.isDebugEnabled()) {

                            LOGGER.debug("use datasource :" + datasourceHolder.get());

                   }

                   LinkedList m = datasourceHolder.get();

                   m.offerFirst(SLAVE);

         }

 

         /**

          * 重置当前栈

          */

         public static void reset() {

                   LinkedList m = datasourceHolder.get();

                   if (LOGGER.isDebugEnabled()) {

                            LOGGER.debug("reset datasource {}", m);

                   }

                   if (m.size() > 0) {

                            m.poll();

                   }

         }

 

         /**

          * 如果是选择使用从库,且从库的数量大于1,则通过取模来控制从库的负载, 计算结果返回AbstractRoutingDataSource

          */

         @Override

         protected Object determineCurrentLookupKey() {

                   LinkedList m = datasourceHolder.get();

                   String key = m.peekFirst() == null ? DEFAULT : m.peekFirst();

 

                   if (null != key) {

                            if (DEFAULT.equals(key)) {

                                     LOGGER.debug("current datasource (default):" + key);

                                     return key;

                            } else if (SLAVE.equals(key)) {

                                     if (slaveSize > 1) {// Slave loadBalance

                                               long c = slaveCount.incrementAndGet();

                                               c = c % slaveSize;

                                               LOGGER.debug("current datasource (slaves>1) :" + SLAVE + (c + 1));

                                               return SLAVE + (c + 1);

                                     } else {

                                               LOGGER.debug("current datasource (slaves=1):" + SLAVE + "1");

                                               return SLAVE + "1";

                                     }

                            }

                            return null;

                   } else {

                            return null;

                   }

         }

 

         public DataSource getMaster() {

                   return master;

         }

 

         public List getSlaves() {

                   return slaves;

         }

 

         public void setMaster(DataSource master) {

                   this.master = master;

         }

 

         public void setSlaves(List slaves) {

                   this.slaves = slaves;

         }

 

}

1.5 注解DataSourceChange

 package com.flame.common.annotation;

 

import static java.lang.annotation.ElementType.METHOD;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

 

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.Target;

 

@Inherited

@Retention(RUNTIME)

@Target(METHOD)

public @interface DataSourceChange {

boolean slave() default false;

}

1.6配置AOP

1. DataSourceAspect切面

package com.flame.common.dataSource;

 

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

 

import com.flame.common.annotation.DataSourceChange;

import com.flame.common.exception.DataSourceAspectException;

 

/**

 * 有{@link com.wangzhixuan.commons.annotation.DataSourceChange}注解的方法,调用时会切换到指定的数据源

 *

 * @author tanghd

 */

@Aspect

@Component

public class DataSourceAspect {

private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceAspect.class);

 

@Around("@annotation(dataSourceChange)")

public Object doAround(ProceedingJoinPoint pjp, DataSourceChange dataSourceChange) {

           LOGGER.debug("AOP切换dataSource");

           Object retVal = null;

           boolean selectedDataSource = false;

           try {

                    if (null != dataSourceChange) {

                             selectedDataSource = true;

                             if (dataSourceChange.slave()) {

                                       DynamicDataSource.useSlave();

                             } else {

                                       DynamicDataSource.useMaster();

                             }

                    }

                    retVal = pjp.proceed();

           } catch (Throwable e) {

                    LOGGER.warn("数据源切换错误", e);

                    throw new DataSourceAspectException("数据源切换错误", e);

           } finally {

                    if (selectedDataSource) {

                             DynamicDataSource.reset();

                    }

           }

           return retVal;

}

}

 

2.修改applicationContext.xml

                    

                  

                  

 

3、service上添加注解

package com.flame.service.impl;

 

import java.util.List;

 

import javax.annotation.Resource;

 

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

 

import com.flame.base.dao.BaseDao;

import com.flame.base.model.DataGrid;

import com.flame.base.model.Page;

import com.flame.base.model.Params;

import com.flame.base.service.BaseServiceImpl;

import com.flame.common.annotation.DataSourceChange;

import com.flame.dao.ArticleDao;

import com.flame.dto.ArticleDto;

import com.flame.entity.Article;

import com.flame.service.ArticleService;

 

@Service("articleService")

public class ArticleServiceImpl extends BaseServiceImpl implements ArticleService {

 

@Resource

private ArticleDao articleDao;

 

@Override

protected BaseDao getBaseDao() {

           return this.articleDao;

}

 

@Override

public List

getResourceByDeviceId(String deviceId) {

           // TODO Auto-generated method stub

           return articleDao.getResourceByDeviceId(deviceId);

}

 

@Override

@DataSourceChange(slave = true)

public DataGrid paging(Params params, Page page) {

           // TODO 自动生成的方法存根

           return articleDao.paging(params, page);

}

 

@Override

@Transactional

public void deleteBatchDo(Long[] id) {

           // TODO 自动生成的方法存根

           for (Long i : id) {

                    articleDao.delete(i);

           }

}

 

}

 

 

详细配置下载:https://download.csdn.net/download/jiangshanmnaa/10829634

你可能感兴趣的:(Mybatis+ MySQL5.7主从数据库复制配置)