springboot mybatis druid 多数据源 注解 low写法

Low的开始

个人不太喜欢xml,xml当然是好的了,青菜萝卜各有所爱 .

于是尝试了下全注解的方式使用springboot mybatis druid多数据源

-----------------------------------------------------------------------------------------

Code

1. yml配置

两个数据源配置,是 同服务器(localhost),同类型(Mysql)不同库(dog,cat) ↓↓↓

spring:
  datasource:
    beginner:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/beginner?useSSL=true&characterEncoding=utf-8
      username: dogcat
      password: 123456
    cat:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/cat?useSSL=true&characterEncoding=utf-8
      username: dogcat
      password: 123456

2. 配置数据源

Beginner 数据源 extends DruidDBConfig(工具类,代码在后面) ↓↓↓

PlatformTransactionManager 事务管理 和 头部的@EnableTransactionManagement一起用

@Configuration
@EnableTransactionManagement
public class DBBeginnerConfiguration extends DruidDBConfig {

    @Value("${spring.datasource.beginner.url}")
    private String url;

    @Value("${spring.datasource.beginner.username}")
    private String username;

    @Value("${spring.datasource.beginner.password}")
    private String password;

    // 注册 spring.datasource.beginner 下配置的基础数据源
    @Bean(name = "datasourceBeginner", initMethod = "init", destroyMethod = "close")
    @Primary
    public DruidDataSource dataSource() {
        return super.buildDataSource(url, username, password);
    }

    @Bean
    @Primary
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

Cat数据源 和上面一样, 就是少了@Primary注解,代码如下: ↓↓↓

@Configuration
@EnableTransactionManagement
public class DBCatConfiguration extends DruidDBConfig {

    @Value("${spring.datasource.cat.url}")
    private String url;

    @Value("${spring.datasource.cat.username}")
    private String username;

    @Value("${spring.datasource.cat.password}")
    private String password;

    // 注册 spring.datasource.dogMapping 下配置的基础数据源
    @Bean(name = "datasourceCat", initMethod = "init", destroyMethod = "close")
    public DruidDataSource dataSource() {
        return super.buildDataSource(url, username, password);
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

PS: 可能有人会问SqlSessionFactory呢,怎么操作DataSource呢,没有xml不需要, (SqlSessionFactory后续API都是基于XML实现对应的CURD),个人初学理解,如果有错,请留言指教,谢谢大家

3. 工具引入类

用于方便设置一堆属性, ↓↓↓

@Import-->DruidManageConfig.class (Druid的管理类)

@EnableConfigurationProperties(DruidDbProperties.class)  里面是一堆属性值的设置

@Configuration
@EnableConfigurationProperties(DruidDbProperties.class)
@Import({DruidManageConfig.class})
public class DruidDBConfig {

    @Resource
    private DruidDbProperties druidDbProperties;

    public DruidDataSource buildDataSource(String url, String username, String password) {
        if (StringUtils.isEmpty(url)) {
            throw new MyException(-2,"Path:DruidDBConfig.buildDataSource DataSource Url lose");
        }

        DruidDataSource datasource = new DruidDataSource();

        datasource.setUrl(url);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(druidDbProperties.getDriverClassName());
        datasource.setInitialSize(druidDbProperties.getInitialSize());
        datasource.setMinIdle(druidDbProperties.getMinIdle());
        datasource.setMaxActive(druidDbProperties.getMaxActive());
        datasource.setMaxWait(druidDbProperties.getMaxWait());
        datasource.setTimeBetweenEvictionRunsMillis(druidDbProperties.getTimeBetweenEvictionRunsMillis());
        datasource.setMinEvictableIdleTimeMillis(druidDbProperties.getMinEvictableIdleTimeMillis());
        datasource.setValidationQuery(druidDbProperties.getValidationQuery());
        datasource.setTestWhileIdle(druidDbProperties.isTestWhileIdle());
        datasource.setTestOnBorrow(druidDbProperties.isTestOnBorrow());
        datasource.setTestOnReturn(druidDbProperties.isTestOnReturn());
        datasource.setConnectProperties(druidDbProperties.getProperties());
        try {
            datasource.setFilters(druidDbProperties.getFilters());
        } catch (SQLException e) {
            throw new MyException(-3,"Path:DruidDBConfig.buildDataSource Druid Filters Error");
        }
        datasource.setConnectionProperties(druidDbProperties.getConnectionProperties());
        return datasource;
    }

}

4. 属性值 配置文件

@ConfigurationProperties(prefix = "druid")
public class DruidDbProperties {
    private String driverClassName = "com.mysql.jdbc.Driver";

    //初始化时建立物理连接的个数初始化发生在显示调用init方法,或者第一次getConnection时
    private int initialSize = 10;

    //最小连接池数量
    private int minIdle = 50;

    //最大连接池数量
    private int maxActive = 300;

    //获取连接时最大等待时间,单位毫秒配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁 
    private int maxWait = 60000;

    /**
     * 有两个含义:
     * 1: Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接
     * 2: testWhileIdle的判断依据,详细看testWhileIdle属性的说明
     */
    private int timeBetweenEvictionRunsMillis = 60000;

    //连接保持空闲而不被驱逐的最长时间
    private int minEvictableIdleTimeMillis = 3600000;

    /**
     * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'
     * 如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用
     */
    private String validationQuery = "SELECT 1";

    /**
     * 建议配置为true,不影响性能,并且保证安全性
     * 申请连接的时候检测,
     * 如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
     */
    private boolean testWhileIdle = true;

    //申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
    private boolean testOnBorrow = false;

    //归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
    private boolean testOnReturn = false;

    /**
     * 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat 日志用的filter:log4j
     * 防御sql注入的filter:wall
     * 1.stat,wall,log4j
     * 2.mergeStat,config,wall
     */
    private String filters = "mergeStat,config,wall";

    private String connectionProperties;

    private Properties properties=new Properties(){
        {
            put("druid.stat.mergeSql", "true");
            put("druid.stat.slowSqlMillis", "5000");
        }
    };

    //白名单
    private String allow;
    //黑名单
    private String deny;

    private String username = "admin";

    private String password = "123456";

    //getter & setter...
}

5. Druid 管理

@EnableConfigurationProperties(DruidDbProperties.class)
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class DruidManageConfig {

    @Resource
    private DruidDbProperties druidDbProperties;

    //druid监控视图配置
    @Bean
    public ServletRegistrationBean druidServlet() {
        ServletRegistrationBean reg = new ServletRegistrationBean();
        reg.setServlet(new StatViewServlet());
        reg.addUrlMappings("/druid/*");

        if (!StringUtils.isEmpty(druidDbProperties.getAllow())) {
            reg.addInitParameter("allow", druidDbProperties.getAllow()); // 白名单
        }
        if (!StringUtils.isEmpty(druidDbProperties.getDeny())) {
            reg.addInitParameter("deny", druidDbProperties.getDeny()); // 黑名单
        }
        reg.addInitParameter("loginUsername", druidDbProperties.getUsername());
        reg.addInitParameter("loginPassword", druidDbProperties.getPassword());
        return reg;
    }

    /**
     * 配置监控拦截器
     * 过滤不需要监控的后缀
     * @return
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }

    //监听Spring 1.定义拦截器
    @Bean
    public DruidStatInterceptor druidStatInterceptor() {
        return new DruidStatInterceptor();
    }

    //定义切入点
    @Bean
    public JdkRegexpMethodPointcut druidStatPointcut() {
        JdkRegexpMethodPointcut druidStatPointcut = new JdkRegexpMethodPointcut();
        String patterns = "com.beginner.mapper.*.*";
        druidStatPointcut.setPatterns(patterns);
        return druidStatPointcut;
    }

    //定义通知类
    @Bean
    public Advisor druidStatAdvisor() {
        return new DefaultPointcutAdvisor(druidStatPointcut(), druidStatInterceptor());
    }
}

6. 搞完了,测一下

Beginner 实体类: 

public class Beginners {
    private Long id;
    private String name;
    private String remark;
    //......
}

Cat 实体类:

public class Cats {
    private Long id;
    private String name;
    private String remark;
}

没区别是因为懒...灰白色的自言自语,绝对看不到, 如果你看到了,以下操作都是一样的

接口 Mapper :  ↓↓↓

这里注意的是主库是beginner,所有对主库进行操作,是直接操作

其他库的操作,需要在表名前面加库名(库名.表明),也就是.yml配置中spring.datasource.url中库的名字

@Mapper
public interface BeginnersMapper {
    @Insert("insert into beginners(name,remark) values(#{name},#{remark})")
    int insert(Beginners beginners);
}
@Mapper
public interface CatsMapper {
    @Insert("insert into cat.cats(name,remark) values(#{name},#{remark})")
    int insert(Cats cats);
}

测试 Controller :  ↓↓↓

@RestController
@RequestMapping("/two")
public class TwoController {
    @Autowired
    private BeginnersMapper beginnersMapper;
    @Autowired
    private CatsMapper catsMapper;
    
    @GetMapping("/beginners")
    public Result beginners_insert() {
        Beginners beginners = new Beginners();
        beginners.setName("beginners");
        beginners.setRemark("beginners_remark");

        beginnersMapper.insert(beginners);
        return ResultUtil.success();
    }

    @GetMapping("/cats")
    public Result cats_insert() {
        Cats cats = new Cats();
        cats.setName("cats");
        cats.setRemark("cats_remark");

        catsMapper.insert(cats);
        return ResultUtil.success();
    }
}

有尝试过 同服务器,不同类型库,但是失败了,因为没有找到不用xml的方式,如果有,请指教留言,谢谢大家

Low 的写法完成,如果有更方便的操作,请大家赐教,谢谢大家

--------------------------------------------------------------------------------------------------

猜你喜欢

转载自my.oschina.net/u/3829444/blog/1810331