美文网首页java成长之路
Spring Boot 集成 Druid + Mybatis

Spring Boot 集成 Druid + Mybatis

作者: Coder_Hohenheim | 来源:发表于2018-02-22 22:15 被阅读1336次

    最近把一个项目的框架由 SpringMVC 转为 Spring Boot,顺便作为学习 Spring Boot 的入门实践。框架的使用入门很快,尤其是 Spring Boot 其实相当于对 SpringMVC 做了一些改进,去除配置,改为代码约定。

    但是,没了配置,第三方库如何集成进来就是我 Spring Boot 入门学习遇到的第一个坎,尤其是一些没有官方支持 Spring Boot 的库。我把我的项目框架转为 Spring Boot 的时候,就遇到了 Druid 和 Mybatis 集成的问题,Mybatis 有支持 Spring Boot 的包,Druid 没有,所以 Druid 的集成就略显麻烦一点。我搜索了很多其他人写的相关 Blog,结果发现很多人要么是互相抄,要么是语焉不详,只是贴出大版的代码,你照抄他的代码虽然也能集成成功,但是你只知其然,不知其所以然,或者有些代码根本是不必要的。

    在走了不少弯路以及持续改进后,我最终以比较满意的结果集成 Druid + Mybatis,为此记录下来,作为个人对近期 Spring Boot 学习总结。本文是针对如何在 Spring Boot 中集成 Druid 和 Mybatis,所以读者必须先熟悉 Spring Boot、Druid 和 Mybatis,对于这三者的细节,不再展开描述。

    引入 Druid 和 Mybatis包:

    在项目 pom.xml 文件中,引入这两个库的 jar 包,其中数据库我是用 MySQL,所以我同时也引入了 MySQL 的驱动 jar 包

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>6.0.6</version>
    </dependency>
    
    <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>druid</artifactId>
       <version>1.1.5</version>
    </dependency>
    
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.1</version>
    </dependency>
    
    <!-- Mybatis 的 jar 包引入的是直接支持 Spring Boot 的,如果是引入是下面的这个 Mybatis 包,就需要自己去实现 Mybais 的配置代码 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    

    集成 Druid:

    Druid 是数据库连接池,负责管理数据库的连接,给Mybatis、JPA提供数据库的连接,所以先集成他进来。
    首先在 Spring Boot 的配置文件中,配置好数据源的各种参数,我的配置文件使用的是 yml,如果你的配置文件为 Properties,请更换为对应的格式即可,我的配置如下:

    spring:
        datasource:
            #DruidDataSource 所需参数
            type: com.alibaba.druid.pool.DruidDataSource 
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/test
            username: 数据库用户名 
            password: 数据库密码 
            initialSize: 3 
            minIdle: 3 
            maxActive: 30 
            maxWait: 15000 
            timeBetweenEvictionRunsMillis: 120000 
            minEvictableIdleTimeMillis: 300000 
            validationQuery: SELECT 'x' 
            testWhileIdle: true 
            testOnBorrow: false 
            testOnReturn: false 
            poolPreparedStatements: false 
            maxPoolPreparedStatementPerConnectionSize: 20 
            removeAbandoned: true 
            removeAbandonedTimeoutMillis: 20000 
            logAbandoned: true 
            logDifferentThread: true 
            filters: log4j,stat 
            connectionProperties:  druid.stat.mergeSql=true;druid.stat.logSlowSql=true;druid.stat.slowSqlMillis=3000 
            useGlobalDataSourceStat: true 
            # Druid 监控 Servlet 配置参数 
            druidRegistrationUrl: /druid/* 
            resetEnable: true 
            loginUsername: 监控后台登录名称 
            loginPassword: 监控后台登录密码 
            # Druid 监控过滤相关配置参数 
            filtersUrlPatterns: /* 
            exclusions: '*.js,*.gif,*.jpg,*.jpeg,*.png,*.css,*.ico,*.jsp,/druid/*'
            sessionStatMaxCount: 2000 
            sessionStatEnable: true 
            principalSessionName: session_user_key 
            profileEnable: true
    

    以上配置参数写好后,Druid 并未按照我们配置的参数进行初始化,因为 Druid 官方并未去实现相关代码,所以我们要自己去实现。

    创建一个 DruidConfig 类,我们在这个类中获取配置文件里面的 spring.datasource 中配置的数据,通过 @Component 和 @ConfigurationProperties(prefix = "spring.datasource") 注解,获取到了配置文件中的配置参数代码如下:

    @Component
    @ConfigurationProperties(prefix = "spring.datasource")
    public class DruidConfig {
        private final Logger logger = LoggerFactory.getLogger(DruidConfig.class);
    
        private String driverClassName;
        private String url;
        private String username;
        private String password;
        private int initialSize;
        private int minIdle;
        private int maxActive;
        private long maxWait;
        private long timeBetweenEvictionRunsMillis;
        private long minEvictableIdleTimeMillis;
        private String validationQuery;
        private boolean testWhileIdle;
        private boolean testOnBorrow;
        private boolean testOnReturn;
        private boolean poolPreparedStatements;
        private int maxPoolPreparedStatementPerConnectionSize;
        private long removeAbandonedTimeoutMillis;
        private boolean removeAbandoned;
        private boolean logAbandoned;
        private boolean logDifferentThread;
        private String filters;
        private String connectionProperties;
        private boolean useGlobalDataSourceStat;
    
        //Druid 监控 Servlet 配置参数
        private String druidRegistrationUrl;
        private boolean resetEnable;
        private String loginUsername;
        private String loginPassword;
    
        // Filters 配置参数
        private String filtersUrlPatterns;
        private String exclusions;
        private int sessionStatMaxCount;
        private boolean sessionStatEnable;
        private String principalSessionName;
        private boolean profileEnable;
    
        …… setter & getter
    }
    

    紧接着就是根据参数,创建 DruidDataSource 了,在 DruidConfig 中,创建一个方法:

    @Bean(initMethod = "init", destroyMethod = "close")
    @Primary
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setInitialSize(initialSize);
        dataSource.setMinIdle(minIdle);
        dataSource.setMaxActive(maxActive);
        dataSource.setMaxWait(maxWait);
        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        dataSource.setValidationQuery(validationQuery);
        dataSource.setTestWhileIdle(testWhileIdle);
        dataSource.setTestOnBorrow(testOnBorrow);
        dataSource.setTestOnReturn(testOnReturn);
        dataSource.setPoolPreparedStatements(poolPreparedStatements);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        dataSource.setRemoveAbandonedTimeoutMillis(removeAbandonedTimeoutMillis);
        dataSource.setRemoveAbandoned(removeAbandoned);
        dataSource.setLogDifferentThread(logDifferentThread);
    
        try {
            dataSource.setFilters(filters);
        }
        catch(SQLException e) {
            e.printStackTrace();
            logger.error("Druid URL过滤设置失败", e);
        }
        dataSource.setConnectionProperties(connectionProperties);
        dataSource.setUseGlobalDataSourceStat(useGlobalDataSourceStat);
    
        return dataSource;
    }
    

    这个方法,就是告诉框架,数据源是由这个方法来提供,注解 @Primary 意思是告诉框架,如果开发者没有指定其他数据源,那么就默认调用这个方法来提供数据源。这一步进行完,其实 Druid 的最核心的配置已经进行完毕,可以使用 Druid 来给 Mybatis 或者 JPA 提供数据库连接了,下面的 Druid 监控可根据实际需求进行配置。

    • 让 Druid 支持事务:通过上面的配置,虽然已经能提供数据库的连接来进行数据库操作了,但是开发过程中,除了调用 SQL,还会遇到调用数据库的事务,所以我们要让 Druid 支持事务才行,让 Druid 支持事务很简单,实现 Spring 的 TransactionManagementConfigurer 接口,重写该接口下的 annotationDrivenTransactionManager 方法,在这个方法里面给 DruidDataSource 开启事务,同时让这个类在 DruidConfig 被 Spring 加载之后,再去被 Spring 加载即可,代码如下:

    @Configuration
    @EnableTransactionManagement
    @AutoConfigureAfter({DruidConfig.class})
    @MapperScan(basePackages = {"Mybatis 的 DAO 接口所在的包路径"})
    public class TransactionConfig implements   TransactionManagementConfigurer {
        @Autowired
        private DruidDataSource mDataSource;
    
        @Override
        public PlatformTransactionManager annotationDrivenTransactionManager() {
            return new DataSourceTransactionManager(mDataSource);
        }
    }
    
    • 配置 Druid 监控页面。Druid 提供了数据库链接状态和 SQL 执行的页面,方便开发者查看自己的程序的数据库连接与操作状态,这个监控后台的页面 Servlet 是 StatViewServlet,我们配置好他,就能打开监控后台查看数据了,在 DruidConfig 中,新增一个如下的方法:

    @Bean
    public ServletRegistrationBean druidServlet() {
        ServletRegistrationBean servletBean = new ServletRegistrationBean(new StatViewServlet(), druidRegistrationUrl);
        servletBean.addInitParameter("resetEnable", String.valueOf(resetEnable));
        servletBean.addInitParameter("loginUsername", loginUsername);
        servletBean.addInitParameter("loginPassword", loginPassword);
    
        return servletBean;
    }
    

    添加这个方法后,重新启动项目,你就能在浏览器中输入 项目URL/你配置的Druid监控后台路径(就是上面druidRegistrationUrl变量) 来访问到 Druid 的监控后台了。

    • 现在是可以访问 Druid 的监控后台了,但是这样的配置不完美,还需要给监控后台加上一些过滤,避免一些没必要的资源和页面被统计进去,所以我们还要配置一个 WebStatFilter,关于 WebStatFilter 的配置参数,请查阅相关文档,我这里只是部分配置参数。我们在 DruidConfig 中,新增一个如下的方法:

    @Bean
    public FilterRegistrationBean filterRegistration() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns(filtersUrlPatterns);
        filterRegistrationBean.addInitParameter("exclusions", exclusions);
        filterRegistrationBean.addInitParameter("sessionStatMaxCount", String.valueOf(sessionStatMaxCount));
        filterRegistrationBean.addInitParameter("sessionStatEnable", String.valueOf(sessionStatEnable));
        filterRegistrationBean.addInitParameter("principalSessionName", principalSessionName);
        filterRegistrationBean.addInitParameter("profileEnable", String.valueOf(profileEnable));
    
        return filterRegistrationBean;
    }
    

    至此,Druid 的配置已全部完成。

    集成 Mybatis:

    Mybatis 的集成就要比 Druid 简单很多,因为我们引入的 org.mybatis.spring.boot 得包,已经帮我们实现了类似于 DruidConfig 的配置类了 image

    所以我们只要在 Spring Boot 中配置好 Mybatis 的参数,写好你的 DAO 和 Service(如果你的 Mybatis 是使用 xml 来写 SQL 方式,就不用实现 Service,如果是注解,就要实现 DAO 的 Service),然后就能使用 Mybatis 了,配置如下,在你的 Spring Boot 中写上如下配置,注意,配置的参数要换上自己的,别照搬代码又不改成自己的参数,然后调用 Mybatis 进行操作发生异常时一头雾水:

    mybatis:
        config-location: classpath:/db/mybatis-config.xml
        mapper-locations: classpath:/db/mappers/**/*Mapper.xml
        type-aliases-package: com.java.springboot.db.entity
    

    结尾:

    至此,Spring Boot 集成 Druid 和 Mybatis 的工作已完成,至于里面的各个参数是什么意思,如何优化,不在本文范围之内,该文只说如何集成。如果文中有任何错误、改进方式,欢迎一起探讨。

    相关文章

      网友评论

      • Java成长之路:1、你上面springboot集成Druid,紧接着是DruidConfig,然后是DruidDataSource,
        2、下面这句话“Mybatis 的集成就要比 Druid 简单很多,因为我们引入的 org.mybatis.spring.boot 得包,已经帮我们实现了类似于 DruidConfig 的配置类了”,是不是 2中的这个jar包 包含了上面的的配置,就不需要在配置了?二选一吗?
        Coder_Hohenheim:不是二选一,我们引入的 Mybatis 的包已经帮我们实现了他自己的 Config 类了,我们不再需要像集成 Druid 那样,去给 Mybatis 创建一个 Config。但是 Druid 抬自己的 Config 还是要创建的,Config 就是每个库他自己的配置参数,相当于 Spring 中的 xml 配置文件。

      本文标题:Spring Boot 集成 Druid + Mybatis

      本文链接:https://www.haomeiwen.com/subject/kvbztftx.html