最近使用ssi框架,参考了一位网友写的ssh数据读写分离及相关资源做了一个ssi的数据读写分离测试,一是给刚刚接触SSI的朋友一个参考,其次也给自己存储下code笔记,有不到位的地方请大家多多指教。
首先介绍我使用相关框架的版本,Spring2.5+struts2.1.6+ibatis2.3,数据库使用的是mysql,使用的jar包请在附件中下载.
1.配置jdbc.properties,由于只是测试,所以读写分离使用的还是一个数据库,同一个用户名和密码.这个可以根据需求修改
#MySQL master 主要数据源 负责数据Update
master.jdbc.driverClassName=com.mysql.jdbc.Driver
master.jdbc.url=jdbc:mysql://localhost:3306/myweb?useUnicode=true&characterEncoding=utf-8
master.jdbc.username=root
master.jdbc.password=root
#MySQL slave 从数据源 负责数据Query
slave.jdbc.driverClassName=com.mysql.jdbc.Driver
slave.jdbc.url=jdbc:mysql://localhost:3306/myweb?useUnicode=true&characterEncoding=utf-8
slave.jdbc.username=root
slave.jdbc.password=root
2.编写数据源处理类
public class DataSourceSwitch {
@SuppressWarnings("rawtypes")
private static final ThreadLocal contextHolder = new ThreadLocal();
@SuppressWarnings("unchecked")
public static void setDataSource(String dataSource) {
Assert.notNull(dataSource, "数据源未创建成功!");
contextHolder.set(dataSource);
}
public static void setMaster() {
contextHolder.remove();
contextHolder.set("master");
}
public static void setSlave() {
contextHolder.remove();
contextHolder.set("slave");
}
public static String getDataSouce(){
return contextHolder.get().toString();
}
}
3.编写数据源AOP切面类
public class DataSourceAdvice implements MethodBeforeAdvice,
AfterReturningAdvice, ThrowsAdvice {
private static Log log = LogFactory.getLog(DataSourceAdvice.class);
private long beginTime=0;
@Override
/**
* SERVICE方法调用结束后调用
*/
public void afterReturning(Object arg, Method method, Object[] args,
Object target) throws Throwable {
log.info("结束业务处理[" + method.getName() + "];耗时:" + (System.currentTimeMillis()-beginTime)+"毫秒;全路径[" +target.getClass().getName()+ "]");
log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
@Override
public void before(Method method, Object[] arg, Object target)
throws Throwable {
log.info("开始业务处理["+method.getName()+"];全路径["+ target.getClass().getName()+"]");
beginTime=System.currentTimeMillis();
log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
if(method.getName().startsWith("add")||method.getName().startsWith("create")
||method.getName().startsWith("del")||method.getName().startsWith("edit")
||method.getName().startsWith("insert")||method.getName().startsWith("save")
||method.getName().startsWith("update")||method.getName().startsWith("modeify")){
log.info("数据源切换到:master");
DataSourceSwitch.setMaster();
log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}else{
log.info("数据源切换到:slave");
DataSourceSwitch.setSlave();
log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
}
/**
* 抛出Exception异常调用
*/
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
log.info("数据源调用发生异常,数据源切换到:slave");
DataSourceSwitch.setSlave();
log.error("数据源调用异常信息:"+ex.getMessage());
log.info("数据源调用异常信息:"+ex.getMessage());
log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
}
4.编写动态数据源切换AOP类
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitch.getDataSouce();
}
}
由于code比较多,所以分开写,在查看的时候也比较方便。