SSM链接多个数据源

SSM链接多个数据源

经过多日研究终于实验成功,以下是我在实验过程中的一些心得:

  • 搭建简单的SSM框架并保证运行成功(自行百度)
  • 配置多个数据源
  • 编写切换数据源代码
  • 注意点

配置多个数据源

在xml下配置数据源`

<bean id = "dataSource_first" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
            <!-- spring整合mybatis后,关于jdbc的配置在mybatis配置文件SqlMapConfig.xml中可以省略 -->
            <property name="driverClass" value="${db.driver}"/>
            <property name="jdbcUrl" value="${db.url}"/>
            <property name="user" value="${db.username}"/>
            <property name="password" value="${db.password}"/>
    </bean>
    <bean id="dataSource_second" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
            <property name="driverClass" value="${db1.driver}"/>
            <property name="jdbcUrl"  value="${db1.url}" />  
            <property name="user"     value="${db1.username}"/>    
            <property name="password" value="${db1.password}"/>  
            >  
    </bean>

    <!-- 动态DataSource配置    -->
    <bean id="dynamicDataSource" class="com.Source.util.DynamicDataSource">  
        <!--默认数据源  -->
        <property name="defaultTargetDataSource" ref="dataSource_second"/>  
        <property name="targetDataSources">  
            <map key-type="java.lang.String">  
                <entry key="dataSource_first" value-ref="dataSource_first"/>  
                <entry key="dataSource_second" value-ref="dataSource_second"/>  
            </map>  
        </property>  
     </bean>
     <bean id = "sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
           <property name="dataSource" ref="dynamicDataSource"/>
            <!-- 指定MyBatis配置文件 -->
            <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"/> 
    </bean>
    <bean id="dataSourceAspect" class="com.Source.util.DataSwitchAop" />
    <aop:config>
        <aop:aspect ref="dataSourceAspect" >
            <!-- 拦截所有service方法 -->
            <!--我这里实在controller上面加的注解,可自行调换  -->
            <aop:pointcut id="dataSourcePointcut" expression="execution(* com.ssm.controller..*.*(..))"/>
            <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
        </aop:aspect>
    </aop:config>
    <!--启动对@AspectJ注解的支持 , proxy-target-class设置为true表示通知spring使用cglib而不是jdk的来生成代理方法,这样AOP可以拦截到Controller -->  
    <aop:aspectj-autoproxy proxy-target-class="true"/> 

注意点
这里写图片描述
这个AOP标签决定了spring的jar包
原因是AOP代理方式有两种:一种是jdk的来生成代理方法,另一种是利用spring使用cglib来生成代理方法,两者代理区别是:jdk的代理面向的是接口代理,而cglib面对具体类代理,不能是接口。如果要在这两种代理方式中自由切换,只需将Spring的版本切换到了4.0.RELEASE 测试。

编写切换数据源代码

代码块

DynamicDataSource类:

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

public class DynamicDataSource extends AbstractRoutingDataSource {  
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceHolder.getDataSource();
    }
}  

DynamicDataSourceHolder 类:

public class DynamicDataSourceHolder {
    private static final ThreadLocal<String> dataSourceKey = new InheritableThreadLocal<String>();

    public static String getDataSource() {
        return dataSourceKey.get();
    }


    public static void setDataSource(String dataSource) {
        dataSourceKey.set(dataSource);
    }


    public static void clearDataSource() {
        dataSourceKey.remove();
    }

}

DataSource类:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//设置注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
public @interface DataSource {
    String value() default "";
}

DataSwitchAop类:


import java.lang.reflect.Method;  
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import com.njwangbo.util.DynamicDataSourceHolder;


public class DataSwitchAop {
      /**
     * 拦截目标方法,获取由@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());
    }
    /**
     * 提取目标对象方法注解和类型注解中的数据源标识
     * 
     * @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());
        }
    }
}

基本上该配置的都配置完了,该写的代码也都差不多了

测试

在controller里写这样一个类

import java.io.IOException;
import java.sql.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class AllController {
    @Autowired
    private LService lService;

    @RequestMapping("/getHotelMsg.action")
    @DataSource(value="dataSource_first")
    @ResponseBody
    public List  queryAll(HttpServletRequest request, HttpServletResponse response) throws IOException {
        List list=null;
        try{
            list=lService.queryAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
}

注意点:请在具体方法下添加@DataSource(value=”dataSource_first”),不要在整个类上面添加

心得

多百度,多尝试,细心点,耐心点,别放弃,希望能够对你的问题有所帮助。
来自多个博主的分享


  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值