原文:http://blog.itpub.net/9399028/viewspace-2106641/
http://blog.csdn.net/a973893384/article/details/21460121
有的時候項目中可能要從另外一個系統取數據 如果另外一個系統能提供接口就很好解決 如果沒有接口 便可以配置多個數據源切換訪問
<1>:這是數據源和事務掃描注入的配置 訪問多個數據源只需要建立多個數據源和事務這一套配置文件
這是第一個數據源
<?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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd" default-lazy-init="true"> <description>Spring公共配置 </description> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:resources.properties</value> <!-- <value>classpath:memcached.properties</value> --> </list> </property> </bean> <!-- dubbo配置 --> <!-- <dubbo:application name="xaUserRegPro" /> <dubbo:registry address="multicast://" /> <dubbo:reference id="userRegProService" interface="com.xinnet.xa.service.UserRegProService" timeout="6000"/> --> <!-- **************** druid 監控連接池配置 ***************** --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 基本屬性 url、user、password --> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="${initialSize}" /> <property name="minIdle" value="${minIdle}" /> <property name="maxActive" value="${maxActive}" /> <!-- 配置獲取連接等待超時的時間 --> <property name="maxWait" value="${maxWait}" /> <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="SELECT 'x'" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- 打開PSCache,並且指定每個連接上PSCache的大小 --> <!-- 如果用Oracle,則把poolPreparedStatements配置為true,mysql可以配置為false。分庫分表較多的數據庫,建議配置為false --> <property name="poolPreparedStatements" value="${poolPreparedStatements}" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> <!-- 對泄漏的連接 自動關閉 --> <property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 打開removeAbandoned功能 --> <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 1800秒,也就是30分鍾 --> <property name="logAbandoned" value="${logAbandoned}" /> <!-- 關閉abanded連接時輸出錯誤日志 --> <!-- 配置監控統計攔截的filters --> <property name="filters" value="mergeStat" /> <!-- <property name="filters" value="stat" /> --> <!-- 慢日志查詢 缺省為3秒 修改為10秒 10000 --> <property name="connectionProperties" value="druid.stat.slowSqlMillis=5000" /> <!-- DruidDataSource各自獨立 , 支持配置公用監控數據 --> <!-- <property name="useGloalDataSourceStat" value="true" /> --> </bean> <!-- druid 監控 spring --> <bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor"/> <bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype"> <property name="patterns"> <list> <value>com.xinnet.*.service.*</value> </list> </property> </bean> <aop:config> <aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" /> </aop:config> <!-- MyBatis Mapper.XMl 配置 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:config/mybatis.xml" /> <property name="mapperLocations"> <list> <!-- 自動匹配Mapper映射文件 --> <value>classpath:mapper/**/*-mapper.xml</value> </list> </property> <!-- 添加插件 --> <property name="plugins"> <array> <ref bean="pagePlugin" /> </array> </property> </bean> <!-- 支持文件上傳相關 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> <!-- 分頁插件,根據方言自動添加分頁信息,默認要求 --> <bean id="pagePlugin" class="com.xinnet.core.mybatis.plugin.PagePlugin"> <property name="properties"> <props> <prop key="dialect">com.xinnet.core.mybatis.dialet.MySQLDialect</prop> <prop key="pageSqlId">.*query.*</prop> </props> </property> </bean> <!-- redis客戶端 --> <!-- jedis pool配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxActive" value="${redis.maxActive}" /> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxWait" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="usePool" value="true"></property> <property name="hostName" value="${redis.host}" /> <property name="port" value="${redis.port}" /> <property name="password" value="${redis.pass}" /> <property name="timeout" value="${redis.timeout}" /> <property name="database" value="${redis.default.db}"></property> <constructor-arg index="0" ref="jedisPoolConfig" /> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> </bean> <!-- ***************事務配置************** --> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <aop:config> <aop:advisor pointcut="execution(* com.xinnet..service..*.*(..))" advice-ref="txAdvice" /> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="true" /> <tx:method name="query*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="load*" read-only="true" /> <tx:method name="select*" read-only="true" /> <tx:method name="count*" read-only="true" /> <tx:method name="search*" read-only="true" /> <tx:method name="list*" read-only="true" /> <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" /> </tx:attributes> </tx:advice> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 開啟注解事務 只對當前配置文件有效 --> <!-- 掃描注解Bean --> <context:component-scan base-package="com.xinnet"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 隱式地向 Spring 容器注冊 --> <context:annotation-config/> </beans>
<2>這是第二個數據源 和第一個數據源一樣 需要有事務 掃描注解
不同的是數據源的 url username 和password 用的是第二個數據源的連接 用戶名和密碼
<?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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd" default-lazy-init="true"> <description>Spring公共配置 </description> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:resources.properties</value> <!-- <value>classpath:memcached.properties</value> --> </list> </property> </bean> <!-- **************** druid 監控連接池配置 ***************** --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 基本屬性 url、user、password --> <property name="url" value="${url2}" /> <property name="username" value="${username2}" /> <property name="password" value="${password2}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="${initialSize}" /> <property name="minIdle" value="${minIdle}" /> <property name="maxActive" value="${maxActive}" /> <!-- 配置獲取連接等待超時的時間 --> <property name="maxWait" value="${maxWait}" /> <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="SELECT 'x'" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- 打開PSCache,並且指定每個連接上PSCache的大小 --> <!-- 如果用Oracle,則把poolPreparedStatements配置為true,mysql可以配置為false。分庫分表較多的數據庫,建議配置為false --> <property name="poolPreparedStatements" value="${poolPreparedStatements}" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> <!-- 對泄漏的連接 自動關閉 --> <property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 打開removeAbandoned功能 --> <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 1800秒,也就是30分鍾 --> <property name="logAbandoned" value="${logAbandoned}" /> <!-- 關閉abanded連接時輸出錯誤日志 --> <!-- 配置監控統計攔截的filters --> <property name="filters" value="mergeStat" /> <!-- <property name="filters" value="stat" /> --> <!-- 慢日志查詢 缺省為3秒 修改為10秒 10000 --> <property name="connectionProperties" value="druid.stat.slowSqlMillis=5000" /> <!-- DruidDataSource各自獨立 , 支持配置公用監控數據 --> <!-- <property name="useGloalDataSourceStat" value="true" /> --> </bean> <!-- druid 監控 spring --> <bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor"/> <bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype"> <property name="patterns"> <list> <value>com.xinnet.*.service.*</value> </list> </property> </bean> <aop:config> <aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" /> </aop:config> <!-- MyBatis Mapper.XMl 配置 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:config/mybatis.xml" /> <property name="mapperLocations"> <list> <!-- 自動匹配Mapper映射文件 --> <value>classpath:mapper/**/*-mapper.xml</value> </list> </property> <!-- 添加插件 --> <property name="plugins"> <array> <ref bean="pagePlugin" /> </array> </property> </bean> <!-- 支持文件上傳相關 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> <!-- 分頁插件,根據方言自動添加分頁信息,默認要求 --> <bean id="pagePlugin" class="com.xinnet.core.mybatis.plugin.PagePlugin"> <property name="properties"> <props> <prop key="dialect">com.xinnet.core.mybatis.dialet.MySQLDialect</prop> <prop key="pageSqlId">.*query.*</prop> </props> </property> </bean> <!-- redis客戶端 --> <!-- jedis pool配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxActive" value="${redis.maxActive}" /> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxWait" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="usePool" value="true"></property> <property name="hostName" value="${redis.host}" /> <property name="port" value="${redis.port}" /> <property name="password" value="${redis.pass}" /> <property name="timeout" value="${redis.timeout}" /> <property name="database" value="${redis.default.db}"></property> <constructor-arg index="0" ref="jedisPoolConfig" /> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> </bean> <!-- ***************事務配置************** --> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <aop:config> <aop:advisor pointcut="execution(* com.xinnet..service..*.*(..))" advice-ref="txAdvice" /> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="true" /> <tx:method name="query*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="load*" read-only="true" /> <tx:method name="select*" read-only="true" /> <tx:method name="count*" read-only="true" /> <tx:method name="search*" read-only="true" /> <tx:method name="list*" read-only="true" /> <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" /> </tx:attributes> </tx:advice> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 開啟注解事務 只對當前配置文件有效 --> <!-- 掃描注解Bean --> <context:component-scan base-package="com.xinnet"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 隱式地向 Spring 容器注冊 --> <context:annotation-config/> </beans>
<3>這個時候就可以用兩個數據源進行切換注入 從而使用不同數據源的service
這是service里面的方法 該怎么寫就是怎么寫 該怎么注解就怎么注解 不用做特殊的步驟
@Service("partyService")
public class PartyServiceImpl implements PartyService {
@Autowired
private PartyDao partyDao;
@Override
public List<Emp> getAllEmp() throws SQLException {
return partyDao.getAllEmp();
}
}
Dao層也是一樣 該怎么寫就怎么寫 該怎么注解就怎么注解
然后可以寫一個測試類試一下連接
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:spring.xml" })//這里的spring.xml加載了第一個數據源 spring-commons.xml public class DataSourceTest extends AbstractTransactionalJUnit4SpringContextTests { /** * * 功能描述:xxxxx * * @throws SQLException * * @author xxx[973893384@163.com] * * @since 2014年3月12日 * * @update:[變更日期YYYY-MM-DD][更改人姓名][變更描述] */ @Test @Rollback(true) public void testGetAllEmp() throws SQLException { ApplicationContext ac = new FileSystemXmlApplicationContext("classpath:config/hymanager/hymanager_spring.xml");//這里加載的是第二個數據源配置文件路徑 使用的時候用application 讀取第二個數據源的配置文件 就可以用getBean 獲取注入的service 不用ac.getBean 用@Autowired自動注入的 則使用的是第一個數據源 PartyService partyService = (PartyService) ac.getBean("partyService"); List<Emp> list = partyService.getAllEmp(); for (Emp emp : list) { System.out.println(emp.getEmpno()); } }
這樣就可以封裝一個父類
public class DataSourceChange { //第二個數據源數據源 public ApplicationContext otherDataSource=new FileSystemXmlApplicationContext("classpath:config/hymanager/hymanager_spring.xml"); //默認數據源 public ApplicationContext defaultDataSource=new FileSystemXmlApplicationContext("classpath:config/spring_commons.xml"); /** * * 功能描述:xxxx * * @param beanName * @return * * @author xxx[973893384@163.com] * * @since 2014年3月12日 * * @update:[變更日期YYYY-MM-DD][更改人姓名][變更描述] */ public Object now(String beanName) { return defaultDataSource.getBean(beanName); } public Object after(String beanName) { return otherDataSource.getBean(beanName); } }
要使用多個數據源的類就可以繼承這個父類
public class HyMangerEmpDataHandle extends DataSourceChange { //用父類的after方法更換配置切換第二套數據源獲取注入partyService private PartyService partyService=(PartyService) after("partyService"); //<span style="font-family: Arial, Helvetica, sans-serif;">用父類的now方法更換配置切換第一套數據源獲取注入empService private EmpService empService=(EmpService) now("empService"); private static Logger log=LoggerFactory.getLogger(PartyService.class); /** * * 功能描述:xxxxx * * @throws SQLException * * @author xxx[973893384@163.com] * * @since 2014年3月12日 * * @update:[變更日期YYYY-MM-DD][更改人姓名][變更描述] */ public void leadingAllEmp() throws SQLException { List<Emp> partyList=partyService.getAllEmp();//第二個數據源注入的service for(Emp emp:partyList) { empService.addEmp(emp);//第一個數據源注入的service } } }
