zoukankan      html  css  js  c++  java
  • ssm使用注解配置多数据源

    在我们刚开始学习编程到初步使用框架开发时,动手去操作数据库对数据进行增删查改就觉得很神奇了,

    那么我们的框架是不是只能连接一个数据库呢,当然不是,百度上有许多关于这方面的资料可以学习

    jdbc的配置,这里我只是简单的用1,2区分

    #oracle
    driver2=oracle.jdbc.driver.OracleDriver
    url2=jdbc:oracle:thin:@localhost:1521:ORCL
    username2=root
    password2=123456

    #mysql1
    driver1=com.mysql.jdbc.Driver
    url1=jdbc:mysql://localhost:3306/jxlz?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
    username1=root
    password1=123456

    #mysql2
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/gslz?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
    username=root
    password=123456

    这是mybatis的配置,有点多配合上下文及注释还是可以理解的 

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:cache="http://www.springframework.org/schema/cache"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context-3.1.xsd
                            http://www.springframework.org/schema/mvc
                            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
                            http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- 自动扫描 -->
        <context:component-scan base-package="com.pskj" annotation-config="true"/><!-- 扫描机制以com.pskj开头的类直接加入到Spring容器管理器中 -->
        <!-- 引入配置文件 数据库-->
        <bean id="propertyConfigurer"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location" value="classpath:jdbc.properties" />
        </bean>
    
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
              destroy-method="close">
            <property name="driverClassName" value="${driver}" />
            <property name="url" value="${url}" />
            <property name="username" value="${username}" />
            <property name="password" value="${password}" />
            <!-- 初始化连接大小 -->
            <property name="initialSize" value="${initialSize}"></property>
            <!-- 连接池最大数量 -->
            <property name="maxActive" value="${maxActive}"></property>
            <!-- 连接池最大空闲 -->
            <property name="maxIdle" value="${maxIdle}"></property>
            <!-- 连接池最小空闲 -->
            <property name="minIdle" value="${minIdle}"></property>
            <!-- 获取连接最大等待时间 -->
            <property name="maxWait" value="${maxWait}"></property>
        </bean>
    
        <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource"
              destroy-method="close">
            <property name="driverClassName" value="${driver1}" />
            <property name="url" value="${url1}" />
            <property name="username" value="${username1}" />
            <property name="password" value="${password1}" />
            <!-- 初始化连接大小 -->
            <property name="initialSize" value="${initialSize}"></property>
            <!-- 连接池最大数量 -->
            <property name="maxActive" value="${maxActive}"></property>
            <!-- 连接池最大空闲 -->
            <property name="maxIdle" value="${maxIdle}"></property>
            <!-- 连接池最小空闲 -->
            <property name="minIdle" value="${minIdle}"></property>
            <!-- 获取连接最大等待时间 -->
            <property name="maxWait" value="${maxWait}"></property>
        </bean>
    
        <bean id="dataSource3" class="org.apache.commons.dbcp.BasicDataSource"
              destroy-method="close">
            <property name="driverClassName" value="${driver2}" />
            <property name="url" value="${url2}" />
            <property name="username" value="${username2}" />
            <property name="password" value="${password2}" />
        </bean>
    
        <!-- 动态DataSource配置    -->
        <bean id="dynamicDataSource" class="com.pskj.GSLZ.utils.dataSource.DynamicDataSource">
            <!--默认数据源  -->
            <property name="defaultTargetDataSource" ref="dataSource3"/>
            <property name="targetDataSources">
                <map key-type="java.lang.String">
                    <entry key="dataSource" value-ref="dataSource"/>
                    <entry key="dataSource2" value-ref="dataSource2"/>
                    <entry key="dataSource3" value-ref="dataSource3"/>
                </map>
            </property>
        </bean>
    
        <bean id="dataSourceAspect" class="com.pskj.GSLZ.utils.dataSource.DataSwitchAop" />
        <aop:config>
            <aop:aspect ref="dataSourceAspect" >
                <!-- 拦截所有service方法 -->
                <!--我这里实在service上面加的注解,可自行调换  -->
                <aop:pointcut id="dataSourcePointcut" expression="execution(* com.pskj.GSLZ.service..*.*(..))"/>
                <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"/>
    
        <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 数据库连接池 -->
            <!--<property name="dataSource" ref="dataSource" />-->
            <property name="dataSource" ref="dynamicDataSource" />
            <!-- 自动扫描mapping.xml文件 -->
            <property name="mapperLocations" value="classpath:mapper/*/*.xml"></property>
            <!--加载mybatis的全局配置文件-->
            <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        </bean>
    
        <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.pskj.GSLZ.dao" />
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        </bean>
    
        <!-- sql会话模版 -->
        <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
            <constructor-arg ref="sqlSessionFactory"/>
        </bean>
    
        <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
        <bean id="transactionManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--<property name="dataSource" ref="dataSource" />-->
            <property name="dataSource" ref="dynamicDataSource" />
        </bean>
    
        <!-- cacheManager工厂类,指定ehcache.xml的位置 -->
        <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
            <property name="configLocation" value="classpath:ehcache.xml" />
            <property name="shared" value="true"/>
        </bean>
    
    </beans>

    还有这个AspectJ等下写类的时候需要用到它的某些方法

     <dependency>
                <groupId>aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.5.2</version>
            </dependency>

    现在开始写可以切换数据源的工具类了

    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());
            }
        }
    }

    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();
        }
    
    }

    DynamicDataSource类:

    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  
    
    public class DynamicDataSource extends AbstractRoutingDataSource {  
        @Override
        protected Object determineCurrentLookupKey() {
            return DynamicDataSourceHolder.getDataSource();
        }
    }  

    控制层和sql语句已经写好

    这是service的代码

        //测试
        @DataSource(value = "dataSource2")
        public PageData listById(PageData pd){
            return (PageData) dao.findForObject("UseMapper.listById",pd);
        }
    @DataSource(value = "dataSource2")我们只要改变这个注解里的value值对应我们想查的数据源即可,经测试无论是mysql还是oracle都成功运行
  • 相关阅读:
    DDoS deflate
    stm32串口
    王立平--GUI与GUILayout的差别
    DOM模型
    Android设计模式(十二)--抽象工厂模式
    Dynamics CRM 开启EmailRouter日志记录
    python in操作引发 TypeError
    为OLED屏添加GUI支持2:2D图形库
    Bloxorz I (poj 3322 水bfs)
    URAL 1823. Ideal Gas(数学啊 )
  • 原文地址:https://www.cnblogs.com/magepi/p/10387938.html
Copyright © 2011-2022 走看看