spring boot之多数据源
来源:互联网 发布:知乎眼睛漂亮的女孩 编辑:程序博客网 时间:2024/06/15 22:29
这个完全是意外收获,看着挺好玩的,就配着玩一下,
话不多说,开始搞,基本的spring boot框架不动,然后在框架上添加东西,我这儿使用mysql和国产oscar数据库开发
注意添加数据库驱动包的依赖
先来application.properties:
server.port=2601spring.application.name=iam-storagespring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.jdbc.Drivercustom.datasource.names=ds1,ds2custom.datasource.ds1.driver-class-name=com.oscar.Drivercustom.datasource.ds1.url=jdbc:oscar://localhost:2003/osrdbcustom.datasource.ds1.username=sysdbacustom.datasource.ds1.password=123456custom.datasource.ds2.driver-class-name=com.oscar.Drivercustom.datasource.ds2.url=jdbc:oscar://localhost:2003/metacustom.datasource.ds2.username=sysdbacustom.datasource.ds2.password=123456mybatis.mapperLocations: classpath:/mybatis/*.xml
最上边是我们默认的我们添加了一个ds1,ds2;我们在项目中用到了默认的数据库mysql和添加的ds1;
先说最后如何用吧
假如用mybatis来查询的话,在service上添加这个注解,其它不变;(不能在mapper的接口上加哦)
@TargetDataSource(name="ds1") public String getMsg4() { // TODO Auto-generated method stub return Integer.toString(testMapper.getMsg4()); }
用jdbcTemplate的话
@TargetDataSource(name="ds1") @SuppressWarnings("unchecked") public String getMsg(){ return jdbcTemplate.query("select * from table2",new ResultSetExtractor() { public Object extractData(ResultSet rs) throws SQLException, DataAccessException { int id = 0 ; while (rs.next()) { id = rs.getInt("id"); } return Integer.toString(id); } }); }
搞定使用方法了,我们现在再回头来看为什么能成功呢,一切都应该我们加的一个bean ,我们在启动类上引用了一个import中的类;
@ComponentScan@MapperScan("org.test2.mapper")@Import({DynamicDataSourceRegister.class})@SpringBootApplicationpublic class Application { public static void main(String args[]){ SpringApplication.run(Application.class); }}
我们看看生成这个注册类的其它配置类
注意比之前添加一个依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDataSourceType(); }}
@Aspect@Order(-1)// 保证该AOP在@Transactional之前执行@Componentpublic class DynamicDataSourceAspect { private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class); @Before("@annotation(ds)") public void changeDataSource(JoinPoint point, TargetDataSource ds) throws Throwable { String dsId = ds.name(); if (!DynamicDataSourceContextHolder.containsDataSource(dsId)) { logger.error("数据源[{}]不存在,使用默认数据源 > {}", ds.name(), point.getSignature()); } else { logger.debug("Use DataSource : {} > {}", ds.name(), point.getSignature()); DynamicDataSourceContextHolder.setDataSourceType(ds.name()); } } @After("@annotation(ds)") public void restoreDataSource(JoinPoint point, TargetDataSource ds) { logger.debug("Revert DataSource : {} > {}", ds.name(), point.getSignature()); DynamicDataSourceContextHolder.clearDataSourceType(); }}
public class DynamicDataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static List<String> dataSourceIds = new ArrayList<>(); public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } public static String getDataSourceType() { return contextHolder.get(); } public static void clearDataSourceType() { contextHolder.remove(); } /** * 判断指定DataSrouce当前是否存在 * * @param dataSourceId * @return */ public static boolean containsDataSource(String dataSourceId){ return dataSourceIds.contains(dataSourceId); }}
/** * 动态数据源注册<br/> * 启动动态数据源请在启动类中(如SpringBootSampleApplication) * 添加 @Import(DynamicDataSourceRegister.class) */public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware { private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceRegister.class); private ConversionService conversionService = new DefaultConversionService(); private PropertyValues dataSourcePropertyValues; // 如配置文件中未指定数据源类型,使用该默认值 private static final Object DATASOURCE_TYPE_DEFAULT = "org.apache.tomcat.jdbc.pool.DataSource"; // private static final Object DATASOURCE_TYPE_DEFAULT = // "com.zaxxer.hikari.HikariDataSource"; // 数据源 private DataSource defaultDataSource; private Map<String, DataSource> customDataSources = new HashMap<>(); @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { Map<Object, Object> targetDataSources = new HashMap<Object, Object>(); // 将主数据源添加到更多数据源中 targetDataSources.put("dataSource", defaultDataSource); DynamicDataSourceContextHolder.dataSourceIds.add("dataSource"); // 添加更多数据源 targetDataSources.putAll(customDataSources); for (String key : customDataSources.keySet()) { DynamicDataSourceContextHolder.dataSourceIds.add(key); } // 创建DynamicDataSource GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClass(DynamicDataSource.class); beanDefinition.setSynthetic(true); MutablePropertyValues mpv = beanDefinition.getPropertyValues(); mpv.addPropertyValue("defaultTargetDataSource", defaultDataSource); mpv.addPropertyValue("targetDataSources", targetDataSources); registry.registerBeanDefinition("dataSource", beanDefinition); logger.info("Dynamic DataSource Registry"); } /** * 创建DataSource * * @param type * @param driverClassName * @param url * @param username * @param password * @return */ @SuppressWarnings("unchecked") public DataSource buildDataSource(Map<String, Object> dsMap) { try { Object type = dsMap.get("type"); if (type == null) type = DATASOURCE_TYPE_DEFAULT;// 默认DataSource Class<? extends DataSource> dataSourceType; dataSourceType = (Class<? extends DataSource>) Class.forName((String) type); String driverClassName = dsMap.get("driver-class-name").toString(); String url = dsMap.get("url").toString(); String username = dsMap.get("username").toString(); String password = dsMap.get("password").toString(); DataSourceBuilder factory = DataSourceBuilder.create().driverClassName(driverClassName).url(url) .username(username).password(password).type(dataSourceType); return factory.build(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } /** * 加载多数据源配置 */ @Override public void setEnvironment(Environment env) { initDefaultDataSource(env); initCustomDataSources(env); } /** * 初始化主数据源 */ private void initDefaultDataSource(Environment env) { // 读取主数据源 RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env, "spring.datasource."); Map<String, Object> dsMap = new HashMap<>(); dsMap.put("type", propertyResolver.getProperty("type")); dsMap.put("driver-class-name", propertyResolver.getProperty("driver-class-name")); dsMap.put("url", propertyResolver.getProperty("url")); dsMap.put("username", propertyResolver.getProperty("username")); dsMap.put("password", propertyResolver.getProperty("password")); defaultDataSource = buildDataSource(dsMap); dataBinder(defaultDataSource, env); } /** * 为DataSource绑定更多数据 * * @param dataSource * @param env */ private void dataBinder(DataSource dataSource, Environment env){ RelaxedDataBinder dataBinder = new RelaxedDataBinder(dataSource); //dataBinder.setValidator(new LocalValidatorFactory().run(this.applicationContext)); dataBinder.setConversionService(conversionService); dataBinder.setIgnoreNestedProperties(false);//false dataBinder.setIgnoreInvalidFields(false);//false dataBinder.setIgnoreUnknownFields(true);//true if(dataSourcePropertyValues == null){ Map<String, Object> rpr = new RelaxedPropertyResolver(env, "spring.datasource").getSubProperties("."); Map<String, Object> values = new HashMap<>(rpr); // 排除已经设置的属性 values.remove("type"); values.remove("driver-class-name"); values.remove("url"); values.remove("username"); values.remove("password"); dataSourcePropertyValues = new MutablePropertyValues(values); } dataBinder.bind(dataSourcePropertyValues); } /** * 初始化更多数据源 * * @author SHANHY * @create 2016年1月24日 */ private void initCustomDataSources(Environment env) { // 读取配置文件获取更多数据源,也可以通过defaultDataSource读取数据库获取更多数据源 RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env, "custom.datasource."); String dsPrefixs = propertyResolver.getProperty("names"); for (String dsPrefix : dsPrefixs.split(",")) {// 多个数据源 Map<String, Object> dsMap = propertyResolver.getSubProperties(dsPrefix + "."); DataSource ds = buildDataSource(dsMap); customDataSources.put(dsPrefix, ds); dataBinder(ds, env); } }}
@Target({ ElementType.METHOD, ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface TargetDataSource { String name();}
好了,大功告成,试着运行一下吧!
test2项目就是配置多数据源的
下载地址:http://download.csdn.net/download/u013289746/9947649
阅读全文
0 0
- spring boot之多数据源
- spring boot jpa之多数据源
- Spring+Mybatis之多数据源配置
- Spring+Mybatis之多数据源配置
- spring boot之多环境配置
- spring boot 配置druid数据源
- spring-boot 集成Druid数据源
- Spring Boot 配置Druid数据源
- Spring Boot集成Druid数据源
- spring boot 动态数据源配置
- Spring Boot+Spring Data Jpa+DBCP2数据源
- Spring Boot 动态数据源(Spring 注解数据源)
- spring-boot-dyna-datasource(spring-boot动态数据源)
- spring boot + JdbcTemplate 使用druid数据源
- spring-boot jpa 配置两个数据源
- Spring boot 数据源未配置异常
- Spring Boot+Mybatis动态数据源配置
- spring boot(12)-数据源配置原理
- 【React全家桶入门之一】引言
- MySQL sum if 的使用
- 快速幂板子
- 文章标题
- C#设计模式(2)——简单工厂模式
- spring boot之多数据源
- 细数机器人大会国内外前沿智能服务机器人大咖
- Java语言switch示例
- ssh连接失败,排错经验
- 用友nc65 uap开发找产品功能源代码
- SequoiaDB巨杉数据库成为唯一入选 “硅谷2016 大数据地形图”中国厂商, 企业级市场超越MongoDB等海外产品
- 线段树
- java中BigDecimal的使用
- video标签支持的视频格式