Spring+Spring MVC +shiro 双数据源
来源:互联网 发布:34周胎儿发育标准数据 编辑:程序博客网 时间:2024/05/23 01:34
最近项目需要去研究了一下spring多数据源的配置和使用,为了后期从多个数据源拉取数据定时进行数据分析和报表统计做准备。由于以前的项目都是单数据源的,没有遇到这种场景,所以也一直没有去了解过如何配置多数据源。
后来发现其实基于spring来配置和使用多数据源还是比较简单的,因为spring框架已经预留了这样的接口可以方便数据源的切换。
第一步:创建一个DynamicDataSource的类,继承AbstractRoutingDataSource并重写determineCurrentLookupKey方法,代码如下:
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceHolder.DynamicDataSource();}}第二步:创建DynamicDataSourceHolder用于持有当前线程中使用的数据源标识,代码如下:
public class DynamicDataSourceHolder {/** * 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰 */private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();/** * * 创 建 人:coates * 创建时间: * 方法描述: 获取数据源 * @return */public static String DynamicDataSource() {return THREAD_DATA_SOURCE.get();}public static void setDataSource(String dataSource){THREAD_DATA_SOURCE.set(dataSource);}/** * * 创 建 人:coates* 创建时间:* 方法描述:删除当前数据源 */public static void clearDataSource(){THREAD_DATA_SOURCE.remove();}
第三步:配置多个数据源和第一步里创建的DynamicDataSource的bean,简化的配置如下:
<context:property-placeholder location="classpath:config/*.properties" /><!-- 数据库连接池 --><bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /><property name="driverClassName" value="${jdbc.driver}" /></bean><bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="${jdbc1.url}" /><property name="username" value="${jdbc1.username}" /><property name="password" value="${jdbc1.password}" /><property name="driverClassName" value="${jdbc.driver}" /></bean><bean id="dynamicDataSource" class="com.shenpinkj.core.tools.datasource.DynamicDataSource"><property name="targetDataSources"><map key-type="java.lang.String"><!-- 指定lookupKey和与之对应的数据源 --><entry key="dataSource1" value-ref="dataSource1"></entry><entry key="dataSource2" value-ref="dataSource2"></entry></map></property><!-- 这里可以指定默认的数据源 --><property name="defaultTargetDataSource" ref="dataSource1" /></bean>
到这里已经可以使用多数据源了,在操作数据库之前只要DynamicDataSourceHolder.setDataSource("dataSource2")即可切换到数据源2并对数据库db2进行操作了。为了方便切换我们试试注解方式
首先,我们得定义一个名为DataSource的注解,代码如下:
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ ElementType.TYPE, ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface DataSource {String value();}
然后,定义AOP切面以便拦截所有带有注解@DataSource的方法,取出注解的值作为数据源标识放到DynamicDataSourceHolder的线程变量中:
import java.lang.reflect.Method;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.reflect.MethodSignature;public class DataSourceAspect {/** * * 创 建 人:coates * 创建时间:2017年11月2日 * 方法描述:拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源 * @param point * @throws Exception */public void intercept(JoinPoint point) throws Exception {Class<?> target = point.getTarget().getClass();MethodSignature signature = (MethodSignature) point.getSignature();// 默认使用目标类型的注解,如果没有则使用其实现接口的注解for (Class<?> clazz : target.getInterfaces()) {resolveDataSource(clazz, signature.getMethod());}resolveDataSource(target, signature.getMethod());}/** * * 创 建 人:coates * 创建时间:2017年11月2日 * 方法描述:提取目标对象方法注解和类型注解中的数据源标识 * @param clazz * @param method */private void resolveDataSource(Class<?> clazz, Method method) {try {Class<?>[] types = method.getParameterTypes();// 默认使用类型注解if (clazz.isAnnotationPresent(DataSource.class)) {DataSource source = clazz.getAnnotation(DataSource.class);DynamicDataSourceHolder.setDataSource(source.value());}// 方法注解可以覆盖类型注解Method m = clazz.getMethod(method.getName(), types);if (m != null && m.isAnnotationPresent(DataSource.class)) {DataSource source = m.getAnnotation(DataSource.class);DynamicDataSourceHolder.setDataSource(source.value());}} catch (Exception e) {System.out.println(clazz + ":" + e.getMessage());}}}最后在spring配置文件中配置拦截规则就可以了,比如拦截service层或者dao层的所有方法:
<bean id="dataSourceAspect" class="com.shenpinkj.core.tools.datasource.DataSourceAspect" /> <aop:config> <aop:aspect ref="dataSourceAspect"> <!-- 拦截所有service方法 --> <aop:pointcut id="dataSourcePointcut" expression="execution(* com.shenpinkj.core.store.service.*.*(..))"/> <aop:before pointcut-ref="dataSourcePointcut" method="intercept" /> </aop:aspect> </aop:config>
这样我们每次都可以通过
@Service@DataSource("dataSource1")public class LogsServiceIpml implements LogsService {@Override@DataSource("dataSource2")public BasePager getLogs(Integer page, Integer rows, String column,Integer order) {}
阅读全文
1 0
- Spring+Spring MVC +shiro 双数据源
- Spring + Spring MVC + mybatis 配置双数据源及用法
- Junit Spring 双数据源
- spring配置双数据源
- spring配置双数据源
- Hibernate spring 双数据源(转载)
- spring+ibatis 双数据源配置
- spring 双数据源 学习备忘
- mybatis+spring双数据源配置
- Spring Boot集成Mybatis双数据源
- Shiro+Spring MVC整合
- Shiro+Spring MVC整合
- spring mvc shiro 配置
- spring mvc + shiro
- Spring+Hibernate双数据源测试Mysql集群读写分离
- Spring+Mybatis+MySql双数据源配置(手动切换数据源)
- 关于spring中的双数据源切换使用
- Spring+SpringMVC+Mybatis使用注解方式配置双数据源
- [LUOGU]P1508 Likecloud-吃、吃、吃
- LAMP环境搭建系列之二:编译安装Mysql5.6.38
- 日期插件laydate.js
- 生产消费者模式 之 实现一个积分系统
- Codeforces Round #446 (Div. 2) B Wrath
- Spring+Spring MVC +shiro 双数据源
- 关于setTimeout与SetInterval定时器
- 大文件断点续传
- 基本常用正则表达式
- 第四周周总结
- 将一个数由几个数的阶乘和表示
- NOIP 2017 D2T1 奶酪
- 19.EasyUI中tree的使用
- android gradle tools 3.X 中依赖,implementation 和compile区别