spring 配置多数据源(mysql读写分离)

前段时间刚换了家新公司,然后看项目代码里用了数据库读写分离的架构,然后好奇扒了代码简单看了下,总体来说就是运用spring aop切面方式来实现的。看明白后就在自己的个人小项目里运用了下,测试OK,所以下面总结下流程:   1、首先定义一个数据源注解,它有两个值,一个对应写库(主库),一个对应读库(从库) 复制代码 package com.jdd.ds; import java.lang.annotation.*; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { String DATA_SOURCE_READ = "dataSourceRead"; String DATA_SOURCE_WRITE = "dataSourceWrite"; String name() default "dataSourceWrite"; } 复制代码   2、在需要拦截的方法上加上该注解 复制代码 package com.jdd.service.impl; import com.jdd.dao.UserDao; import com.jdd.ds.DataSource; import com.jdd.pojo.User; import com.jdd.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service("userService") public class UserServiceImpl implements UserService{ @Autowired private UserDao userDao; @DataSource(name=DataSource.DATA_SOURCE_READ) @Override public User getUserByNameAndPassword(String name, String password) { return userDao.getUserByNameAndPassword(name, password); } @DataSource(name=DataSource.DATA_SOURCE_WRITE) @Override public int insertUser(User user) { return userDao.insertUser(user); } } 复制代码   3、然后在配置文件里加上aop切面配置: 复制代码 复制代码   4、然后我们要在切面类里,获取到方法上的dataSource注解里设置的值,从而决定使用哪个数据源 复制代码 package com.jdd.ds; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Method; public class DataSourceExchange { private static Logger logger = LoggerFactory.getLogger(DataSourceExchange.class); public Object execute(ProceedingJoinPoint pjp){ logger.info("DataSourceExchange==>"); Object obj = null; Signature signature = pjp.getSignature(); MethodSignature methodSignature = (MethodSignature)signature; Method targetMethod = methodSignature.getMethod(); Method realMethod = null; try { realMethod = pjp.getTarget().getClass().getDeclaredMethod(signature.getName(), targetMethod.getParameterTypes()); if(realMethod.isAnnotationPresent(DataSource.class)){ DataSource datasource = (DataSource) realMethod.getAnnotation(DataSource.class); DataSourceContext.setDbType(datasource.name()); logger.info(realMethod.getName() +" set dbtype==>"+datasource.name()); }else{ DataSourceContext.setDbType("dataSourceWrite"); } obj = pjp.proceed(); } catch (Throwable t) { t.printStackTrace(); } logger.info(realMethod.getName()+" clear datatype==>"); DataSourceContext.clearDbType(); return obj; } } 复制代码   在方法执行前,设置具体数据源,然后方法执行完后,再清除掉该值。   注:注意上面的通过反射获取业务方法的代码, 开始的时候用   MethodSignature signature = (MethodSignature)pjp.getSignature();   Method method = signature.getMethod();   发现通过这种方法获取的method,它是没有注解信息的。后来在网上搜了下,大概说是这种方法获取的是代理方法,不是目标方法。代理方法是不带注解信息的,所以这块注意下。   5、下面看下 DataSourceContext 类,作用自然就是设置数据源上下文。 复制代码 package com.jdd.ds; public class DataSourceContext { public static final String DATA_SOURCE_READ = "dataSourceRead"; public static final String DATA_SOURCE_WRITE = "dataSourceWrite"; private static final ThreadLocal contextHolder = new ThreadLocal(); public DataSourceContext(){ } public static void setDbType(String dbType){ contextHolder.set(dbType); } public static String getDbType(){ return (String)contextHolder.get(); } public static void clearDbType(){ contextHolder.remove(); } } 复制代码   6、下面定义 MultipleDataSource类, 继承与spring的 AbstractRoutingDataSource类, 并重写它的 determineCurrentLookupKey 方法, 作用就是从上下文获取当前线程使用的数据源标识: 复制代码 package com.jdd.ds; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class MultipleDataSource extends AbstractRoutingDataSource{ @Override protected Object determineCurrentLookupKey() { Object key = DataSourceContext.getDbType(); if(key != null){ this.logger.info("当前线程使用的数据源标识为 [ " + key.toString() + " ]."); } return key; } } 复制代码   7、最后在 配置文件 applicationContext-mysql.xml 里 配上数据源 复制代码 复制代码   8、到这里和spring相关的配置基本就配完了, 其实后面还要再配置一下 mysql的主从复制,就是对写库的操作都同步到从库,这样写库从库的数据才一致。具体配置操作我就不写了,可以自行到网上搜索。 https://www.cnblogs.com/xiexin2015/p/8998647.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信