• SpringBoot系列七:SpringBoot 整合 MyBatis(配置 druid 数据源、配置 MyBatis、事务控制、druid 监控)


    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅。

    1、概念:SpringBoot 整合 MyBatis

    2、背景

      SpringBoot 得到最终效果是一个简化到极致的 WEB 开发,但是只要牵扯到 WEB 开发,就绝对不可能缺少数据层操作,所有的开发都一定秉持着 MVC 设计模式的原则,MVC 里面业务层不可少,数据层永远要与业务层绑定在一起,既然要进行数据层的操作,那么肯定首选的一定就是 MyBatis,因为 MyBatis 整合处理之后尤其是与 Spring 整合里面可以直接避免掉 DAO 层的编写, 同时 VO 类也是最干净的,这一点上绝对要比其它的 ORMapping 组件都方便。

    2.1、配置 druid 数据源

    这个数据库连接池的配置是由阿里提供的,并且由于其性能很高,同时具备有很好的监控性,在实际的开发之中已经开始广泛的使用了。

    1、 首先编写一个数据库创建脚本:

    DROP DATBASE IF EXISTS study ;
    CREATE DATBASE study CHARACTER SET UTF8 ;
    USE study ;
    CREATE TABLE dept (
        deptno        BIGINT        AUTO_INCREMENT ,
        dname        VARCHAR(50) ,
        CONSTRAINT pk_deptno PRIMARY KEY(deptno)
    ) ;
    INSERT INTO dept(dname) VALUES ('开发部') ;
    INSERT INTO dept(dname) VALUES ('财务部') ;
    INSERT INTO dept(dname) VALUES ('市场部') ;
    INSERT INTO dept(dname) VALUES ('后勤部') ;
    INSERT INTO dept(dname) VALUES ('公关部') ;

    2、 随后要进行druid 的数据源的配置,如果要想使用druid 的数据源,那么首先一定要去修改 pom.xml 配置文件,引入以下包:

                 <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.0.4</version>
                </dependency>
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid</artifactId>
                    <version>1.0.31</version>
                </dependency>

    3、 如果要进行数据源的整合处理,直接修改 application.yml 配置文件即可:

    server:
      port: 80
    spring:
      messages:
        basename: i18n/Messages,i18n/Pages
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource    # 配置当前要使用的数据源的操作类型
        driver-class-name: org.gjt.mm.mysql.Driver      # 配置MySQL的驱动程序类
        url: jdbc:mysql://localhost:3306/study           # 数据库连接地址
        username: root                                  # 数据库用户名
        password: mysqladmin                            # 数据库连接密码
        dbcp2:                                          # 进行数据库连接池的配置
          min-idle: 5                                   # 数据库连接池的最小维持连接数    
          initial-size: 5                               # 初始化提供的连接数
          max-total: 5                                  # 最大的连接数
          max-wait-millis: 200                          # 等待连接获取的最大超时时间

    4、 如果这个时候你需要进行 junit 代码测试,则一定要将 mybatis 开发包配置过来,因为只有在 mybatis 开发包里面才会将 druid 的配置的数据库连接池变为所需要的 DataSource 数据源对象。

                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>1.3.0</version>
                </dependency>

    5、 测试一下当前的连接池是否可用

    package cn.study.microboot.test;
    
    import javax.annotation.Resource;
    import javax.sql.DataSource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    
    import cn.study.microboot.StartSpringBootMain;
    
    @SpringBootTest(classes = StartSpringBootMain.class)
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    public class TestDataSource {
        @Resource
        private DataSource dataSource;
        @Test
        public void testConnection() throws Exception {
            System.out.println(this.dataSource);
        }
    }

    此时可以获取数据库连接,表示当前的 druid 的配置正确。

    2.2、配置 MyBatis

    如果要进行 mybatis 的配置一定要导入 spring-boot 所支持的 mybatis 开发包。

                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>1.3.0</version>
                </dependency>

    1、 随后要去修改 application.yml 配置文件,追加 mybatis 的相关配置项:

    mybatis:
      config-location: classpath:mybatis/mybatis.cfg.xml    # mybatis配置文件所在路径
      type-aliases-package: cn.study.microboot.vo            # 定义所有操作类的别名所在包
      mapper-locations:                                     # 所有的mapper映射文件
      - classpath:mybatis/mapper/**/*.xml

    2、 建立一个 Dept 的 VO 类:

    package cn.study.microboot.vo;
    
    import java.io.Serializable;
    
    @SuppressWarnings("serial")
    public class Dept implements Serializable {
        private Long deptno ;
        private String dname ;
        public Long getDeptno() {
            return deptno;
        }
        public void setDeptno(Long deptno) {
            this.deptno = deptno;
        }
        public String getDname() {
            return dname;
        }
        public void setDname(String dname) {
            this.dname = dname;
        }
        @Override
        public String toString() {
            return "Dept [deptno=" + deptno + ", dname=" + dname + "]";
        }
    }

    3、 在 src/main/resources 目录下建立有一个 mybatis/mybatis.cfg.xml 配置文件:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration   
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"   
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!-- 进行Mybatis的相应的环境的属性定义 -->
        <settings>    <!-- 在本项目之中开启二级缓存 -->
            <setting name="cacheEnabled" value="true"/>
        </settings>
    </configuration>

    4、 src/main/resources/mybatis 下建立有一个 mapper 子目录,而后在里面定义有 cn/mldn/Dept.xml 配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="cn.study.microboot.dao.IDeptDAO">
        <select id="findAll" resultType="Dept">
            SELECT deptno,dname FROM dept ;
        </select>
    </mapper>  

    5、 建立 IDeptDAO 接口,注意接口所在的包:

    package cn.study.microboot.dao;
    
    import java.util.List;
    
    import org.apache.ibatis.annotations.Mapper;
    
    import cn.study.microboot.vo.Dept;
    @Mapper
    public interface IDeptDAO {
        public List<Dept> findAll() ;
    }

    在定义 DAO 接口的时候由于需要自动生成实现子类,所以在接口声明处一定要编写有一个“@Mapper”注解,否则你的 DAO 接口和*.xml 的 Mapper 文件无法整合在一起。

    6、 建立一个 IDeptService 接口,作为服务使用:

    package cn.study.microboot.service;
    
    import java.util.List;
    
    import cn.study.microboot.vo.Dept;
    
    public interface IDeptService {
        public List<Dept> list() ;
    }
    package cn.study.microboot.service.impl;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    
    import org.springframework.stereotype.Service;
    
    import cn.study.microboot.dao.IDeptDAO;
    import cn.study.microboot.service.IDeptService;
    import cn.study.microboot.vo.Dept;
    @Service
    public class DeptServiceImpl implements IDeptService {
        @Resource
        private IDeptDAO deptDAO;
        @Override
        public List<Dept> list() {
            return this.deptDAO.findAll();
        }
    
    }

    7、 进行代码测试类的编写:

    package cn.study.microboot.test;
    
    import javax.annotation.Resource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    
    import cn.study.microboot.StartSpringBootMain;
    import cn.study.microboot.service.IDeptService;
    
    @SpringBootTest(classes = StartSpringBootMain.class)
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    public class TestDeptService {
        @Resource
        private IDeptService deptService;
        @Test
        public void testList() throws Exception {
            System.out.println(this.deptService.list());
        }
    }

    此时测试通过,则 SpringBoot 与 MyBatis 已经可以成功的整合在一起进行项目开发,此时的配置要比之前使用 Spring + Mybatis 直接配置简单 N 多倍。

    2.3、事务控制

    1、 修改 IDeptService 接口,追加一个只读事务控制:

    package cn.study.microboot.service;
    
    import java.util.List;
    
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import cn.study.microboot.vo.Dept;
    
    public interface IDeptService {
        @Transactional(readOnly = true)
        public List<Dept> list() ;
    }

    此时配置了一个只读的事务操作,那么也就是说在这个业务方法只能够采用读的模式来进行操作。

    2、 但是现在你配置了一个注解并不表示当前已经合理的支持了事务,如果要进行事务的启用,还需要在程序启动类上追加一个 新的注解配置:

    package cn.study.microboot;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    @SpringBootApplication    // 启动SpringBoot程序,而后自带子包扫描
    @EnableTransactionManagement
    public class StartSpringBootMain {
        public static void main(String[] args) throws Exception {
            SpringApplication.run(StartSpringBootMain.class, args);
        }
    }

    3、 如果现在要想更好的观察到事务的问题,最简单的做法是编写一个数据增加操作,而后为这个业务方法设置只读配置。

    · 修改 IDeptDAO 接口追加一个新的方法:

    package cn.study.microboot.dao;
    
    import java.util.List;
    
    import org.apache.ibatis.annotations.Mapper;
    
    import cn.study.microboot.vo.Dept;
    @Mapper
    public interface IDeptDAO {
        public List<Dept> findAll();
        public boolean doCreate(Dept vo) ;
    }

    · 修改 Dept.xml 配置文件,追加一个方法的实现 SQL 语句:

    <insert id="doCreate" parameterType="Dept">
            INSERT INTO dept(dname) VALUES (#{dname}) ;
    </insert>

    · 在 IDeptService 接口之中追加有一个业务方法:

    @Transactional((readOnly = true)
        public boolean add(Dept vo) ;

    · 编写测试方法:

        @Test
        public void testAdd() throws Exception {
            Dept dept = new Dept();
            dept.setDname("测试部");
            System.out.println(this.deptService.add(dept));
        }

    此时会报错

    4、 如果在实际的工作之中,对于更新操作应该强制性的启动一个事务控制才对:

    @Transactional(propagation=Propagation.REQUIRED)
    public boolean add(Dept vo) ;

    此时应该明确的表示该操作方法应该启动有一个事务的配置项。

    5、 在使用Spring+MyBatis里面处理的时候应该考虑到信息显示问题,所以此处建议使用logback日志组件来进行日志信息的配置;

    · 将 logback.xml 配置文件拷贝到 src/main/resources 目录之中;

    <?xml version="1.0" encoding="UTF-8"?>
    
    <configuration scan="true">
        <property name="APP" value="${project.artifactId}" />
        <property name="LOG_HOME" value="/data/www/log/${APP}" />
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0} %X{ServiceId} - %m%n</pattern>
            </encoder>
        </appender>
        <appender name="DETAIL"
            class="ch.qos.logback.core.rolling.RollingFileAppender" additivity="false">
            <File>${LOG_HOME}/${APP}_detail.log</File>
            <encoder>
                <pattern>%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0} %X{ServiceId} - %m%n</pattern>
            </encoder>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_HOME}/${APP}_detail.log.%d{yyyyMMdd}</fileNamePattern>
            </rollingPolicy>
        </appender>
        <appender name="ACCESS"
            class="ch.qos.logback.core.rolling.RollingFileAppender" additivity="false">
            <File>${LOG_HOME}/${APP}_access.log</File>
            <encoder>
                <pattern>%d{yy-MM-dd.HH:mm:ss.SSS};%X{ServiceId};%m%n</pattern>
            </encoder>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_HOME}/${APP}_access.log.%d{yyyyMMdd}</fileNamePattern>
            </rollingPolicy>
        </appender>
    
    
        <logger name="ACCESS">
            <appender-ref ref="ACCESS" />
        </logger>
        <logger name="druid.sql.Statement" level="DEBUG" />
        <logger name="cn.study.microboot.dao" level="TRACE" />
    
        <root level="INFO">
            <appender-ref ref="DETAIL" />
            <appender-ref ref="CONSOLE" />
        </root>
    </configuration>

    · 在项目之中去引入 logback 的依赖程序文件:

             <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
            </dependency>

    · 在正常情况下 mybatis 中的日志信息的输出操作必须设置其对应的命名空间,在 logback.xml 中追加如下信息:

     <logger name="cn.study.microboot.dao" level="TRACE" />

    2.4、druid 监控

    druid 数据库连接池之所以使用非常广泛,其最主要的原因在于它可以直接提供性能监控。那么本次来针对于当前已经实现好 的 druid 配置来进行性能监控的处理配置。

    1、 如果要想进行 Druid 的性能的监控操作,则需要做一些基础配置,例如:你访问的 IP 地址是否是白名单。

    package cn.study.microboot.config;
    
    import javax.sql.DataSource;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.boot.web.servlet.ServletRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import com.alibaba.druid.support.http.StatViewServlet;
    import com.alibaba.druid.support.http.WebStatFilter;
    
    @Configuration
    public class DruidConfig {
        @Bean
        public ServletRegistrationBean druidServlet() { // 主要实现WEB监控的配置处理
            ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
                    new StatViewServlet(), "/druid/*"); // 现在要进行druid监控的配置处理操作
            servletRegistrationBean.addInitParameter("allow",
                    "127.0.0.1,192.168.1.159"); // 白名单
            servletRegistrationBean.addInitParameter("deny", "192.168.1.200"); // 黑名单
            servletRegistrationBean.addInitParameter("loginUsername", "studyjava"); // 用户名
            servletRegistrationBean.addInitParameter("loginPassword", "hello"); // 密码
            servletRegistrationBean.addInitParameter("resetEnable", "false"); // 是否可以重置数据源
            return servletRegistrationBean ;
        }
        @Bean
        public FilterRegistrationBean filterRegistrationBean() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ;
            filterRegistrationBean.setFilter(new WebStatFilter());
            filterRegistrationBean.addUrlPatterns("/*"); // 所有请求进行监控处理
            filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*");
            return filterRegistrationBean ;
        }
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource")
        public DataSource druidDataSource() {
            return new DruidDataSource();
        }
    }

    2、 为了更好的说明问题,建议建立一个控制器进行业务层的调用;

    package cn.study.microboot.controller;
    
    import javax.annotation.Resource;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import cn.study.microboot.service.IDeptService;
    import cn.study.microboot.util.controller.AbstractBaseController;
    
    @RestController
    public class DeptController extends AbstractBaseController {
        @Resource
        private IDeptService deptService ;
        @RequestMapping(value = "/list", method = RequestMethod.GET)
        public Object list() { // 通过model可以实现内容的传递
            return this.deptService.list() ; 
        }
    }

    3、 如果要想进行监控还需要开启一个过滤配置,而这个过滤配置的开启需要通过 application.yml 文件配置;

    spring:
      messages:
        basename: i18n/Messages,i18n/Pages
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource    # 配置当前要使用的数据源的操作类型
        driver-class-name: org.gjt.mm.mysql.Driver      # 配置MySQL的驱动程序类
        url: jdbc:mysql://localhost:3306/study           # 数据库连接地址
        username: root                                  # 数据库用户名
        password: mysqladmin                            # 数据库连接密码
        filters: stat,wall,log4j
        dbcp2:                                          # 进行数据库连接池的配置
          min-idle: 5                                   # 数据库连接池的最小维持连接数    
          initial-size: 5                               # 初始化提供的连接数
          max-total: 5                                  # 最大的连接数
          max-wait-millis: 200                          # 等待连接获取的最大超时时间

    启动项目,在浏览器地址栏输入http://localhost/druid,然后输入用户名studyjava,密码hello就可以看到监控页面了

    利用监控可以方便的进行程序的管理,这一点在企业开发之中至关重要。

  • 相关阅读:
    OpenCV 图像旋转
    单链表插入与删除数据
    opencv 数据训练
    C++ 小波变换
    二十七、miniscrapy,scrapy源码初解
    二十六、Scrapy自定义命令
    二十五、scrapy中的去重规则及自定义
    二十四、在scrapy中如何获取cookies
    十六、 IO多路复用,异步非阻塞
    五、IO模型简介
  • 原文地址:https://www.cnblogs.com/leeSmall/p/8719455.html
Copyright © 2020-2023  润新知