SpringBoot 整合 Mybatis + Druid + Swagger2

转载出处: https://blog.csdn.net/greedystar/article/details/81020248

一、添加依赖

二、配置

(一)配置文件

(二)配置类

三、测试

(一)Druid监控

(二)日志记录

(三)在线API文档

四、总结


本文以Maven构建SpringBoot项目,并整合Mybatis、Druid和Swagger2,实现Druid监控和在线API文档的功能。

一、添加依赖

pom.xml中依赖包如下所示:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions> <!-- 去掉Spring默认的日志插件 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 热部署 修改classpath下的文件springboot自动重启 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

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

        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <!-- log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.15</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- api文档 swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.2.2</version>
        </dependency>
    </dependencies>

二、配置

(一)配置文件

Druid、Mybatis和log4j2能够很好的支持SpringBoot,这里直接在配置文件application.yml中对其进行配置,配置项的描述已经在文件中进行了注释,这里就不多说了,application.yml内容如下:

我们可以看到,使用SpringBoot后,需要进行的配置的确变简单了,这就是“习惯优于配置”为我们带来的便利。

从此以后,再也不用对老板说:别急,我马上就要配置完了!

附:DruidDataSource配置属性列表

server:
  port: 8088
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/spring-boot-demo?useUnicode=true&characterEncoding=utf8
      username: test
      password: 43997k7k
      # 初始化时建立的连接数
      initial-size: 5
      # 最大连接数
      max-active: 20
      # 最小连接数
      min-idle: 5
      # 获取连接最大等待时间,单位:毫秒
      max-wait: 2000
      # 是否缓存preparedStatement
      pool-prepared-statements: false
      # 最大preparedStatement缓存数,当pool-prepared-statements=true时需要大于0
      max-pool-prepared-statement-per-connection-size: -1
      # 检测连接是否失效的sql
      validation-query: SELECT 'x'
      # 检测连接是否失效的超时时间,单位:秒
      validation-query-timeout: 2
      filters: stat,wall,log4j2
      # Spring aop监控的包路径
      aop-patterns: cn.greedystar.springbootdemo.modules.service.*
      filter:
        # 监控统计
        stat:
          enabled: true
          db-type: mysql
          # 打印慢sql
          log-slow-sql: true
          # 超过200毫秒即为慢sql
          slow-sql-millis: 200
        # sql防火墙
        wall:
          enabled: true
          db-type: mysql
          # 对认定的攻击sql进行日志输出
          log-violation: true
          # 对认定的攻击sql抛出异常
          throw-exception: true
          config:
            # 是否允许下述操作
            alter-table-allow: false
            truncate-allow: false
            drop-table-allow: false
            update-where-none-check: true
            # metadata会暴露数据的表结构
            metadata-allow: false
        # 日志
        log4j2:
          enabled: true
          # log4j2仅记录druid的sql执行日志
          statement-log-enabled: false
          connection-log-enabled: false
          result-set-log-enabled: false
          statement-executable-sql-log-enable: true
      # 数据库连接池监控统计插件
      web-stat-filter:
        enabled: true
        url-pattern: /*
        # 过滤掉如下请求
        exclusions: '*.gif,*.png,*.jpg,*.html,*.js,*.css,*.ico,/druid/*'
      # 数据库连接池监控页面插件
      stat-view-servlet:
        enabled: true
        url-pattern: '/druid/*'
        reset-enable: true
        login-username: admin
        login-password: admin
        allow:
        deny:

  # 设置cglib代理模式,防止非接口代理出错
  aop:
    proxy-target-class: true

# mybatis映射文件路径
mybatis:
  mapper-locations: classpath*:mybatis/*Mapper.xml
# 日志配置文件
logging:
  config: classpath:log4j2.xml

log4j2配置文件log4j2.xml参考自Druid的官方wiki:Druid中使用log4j2进行日志输出,将日志输出级别改为了INFO,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="OFF">
    <appenders>

        <Console name="Console" target="SYSTEM_OUT">
            <!--只接受程序中INFO级别的日志进行处理-->
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss.SSS}] %-5level %class{36} %L %M - %msg%xEx%n"/>
        </Console>

        <!--处理DEBUG级别的日志,并把该日志放到logs/debug.log文件中-->
        <!--打印出DEBUG级别日志,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileDebug" fileName="./logs/debug.log"
                     filePattern="logs/$${date:yyyy-MM}/debug-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="DEBUG"/>
                <ThresholdFilter level="INFO" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout
                    pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %class{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="500 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile>

        <!--处理INFO级别的日志,并把该日志放到logs/info.log文件中-->
        <RollingFile name="RollingFileInfo" fileName="./logs/info.log"
                     filePattern="logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <!--只接受INFO级别的日志,其余的全部拒绝处理-->
                <ThresholdFilter level="INFO"/>
                <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout
                    pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %class{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="500 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile>

        <!--处理WARN级别的日志,并把该日志放到logs/warn.log文件中-->
        <RollingFile name="RollingFileWarn" fileName="./logs/warn.log"
                     filePattern="logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="WARN"/>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout
                    pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %class{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="500 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile>

        <!--处理error级别的日志,并把该日志放到logs/error.log文件中-->
        <RollingFile name="RollingFileError" fileName="./logs/error.log"
                     filePattern="logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
            <ThresholdFilter level="ERROR"/>
            <PatternLayout
                    pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %class{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="500 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile>

        <!--druid的日志记录追加器-->
        <RollingFile name="druidSqlRollingFile" fileName="./logs/druid-sql.log"
                     filePattern="logs/$${date:yyyy-MM}/api-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %L %M - %msg%xEx%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="500 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile>
    </appenders>

    <loggers>
        <root level="INFO">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
            <appender-ref ref="RollingFileDebug"/>
        </root>

        <!--记录druid-sql的记录-->
        <logger name="druid.sql.Statement" level="debug" additivity="false">
            <appender-ref ref="druidSqlRollingFile"/>
        </logger>
        <logger name="druid.sql.Statement" level="debug" additivity="false">
            <appender-ref ref="druidSqlRollingFile"/>
        </logger>

        <!--log4j2 自带过滤日志-->
        <Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
        <Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
        <Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
        <logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
        <Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
        <Logger name="org.crsh.plugin" level="warn" />
        <logger name="org.crsh.ssh" level="warn"/>
        <Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
        <Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
        <logger name="org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration" level="warn"/>
        <logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
        <logger name="org.thymeleaf" level="warn"/>
    </loggers>
</configuration>

到这里,Druid的配置就算完成了。

Mybatis的配置除了在配置文件中指定Mapper映射文件的路径外,还要告知应用程序扫描Mapper接口,有两种方式可以实现:

其一,在应用程序入口类上加上Mapper接口的扫描@MapperScan,并指定Mapper接口的包路径,如下所示:

@SpringBootApplication
@MapperScan("cn.greedystar.springbootdemo.modules.dao")
public class SpringBootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }
}

其二,在Mapper接口类上加上注解@Mapper,如下所示:

@Mapper
public interface UserDao extends BaseDao<User> {
    List<User> findUserList(User user);
}

注意:网上很多资料将以上两种配置方式形容为必须一起使用,这种情况下还是要自己多试一试。

至此,Druid和Mybatis的配置工作就完成了。

(二)配置类

这里使用了Spring3.0引入的注解@Configuration,在@Configuration注解的类中可以定义多个由@Bean注解的方法,用于创建Bean,与在配置文件中定义<bean>的效果是一样的,本文中使用@Configuration注解配置Swagger2,如下所示:

@Configuration
@EnableSwagger2
@ComponentScan({"cn.greedystar.springbootdemo.modules.web"})
public class Swagger2Config {
    /**
     * 创建API应用
     * apiInfo() 增加API相关信息
     * 通过select()函数返回一个ApiSelectorBuilder实例,指定扫描的包路径来定义要建立API的controller目录。
     *
     * @return
     */
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("cn.greedystar.springbootdemo.modules.web"))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 创建该API的基本信息(这些基本信息会展现在文档页面中)
     * 访问地址:http://项目实际地址/swagger-ui.html
     *
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("利用swagger构建api文档")
                .description("更多请关注 http://blog.csdn.net/greedystar")
                .termsOfServiceUrl("http://blog.csdn.net/greedystar")
                .version("1.0")
                .build();
    }
}

Swagger2的配置中指定了扫描controller的路径,下面我们来看一看controller中如何配置Api文档的数据,在下面这段代码中,我们使用了@ApiOperation和@ApiImplicitParam来配置Api文档的数据,具体如下所示:

@RestController
@RequestMapping(value = "/user/")
public class UserController {
    @Autowired
    private UserService userService;

    @ApiOperation(value = "获取所有用户列表", notes = "获取所有用户列表")
    @RequestMapping(value = "list", method = RequestMethod.GET)
    public Response getAllUser() {
        List<User> userList = userService.findList(new User());
        if (userList == null) {
            return new Response.Builder().setMessage("no data found").setStatus(404).build();
        }
        return new Response.Builder().setMessage("OK").setStatus(200).setData(userList).build();
    }

    @ApiOperation(value = "获取用户详细信息", notes = "根据id来获取用户详细信息")
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "String", paramType = "path")
    @RequestMapping(value = "{id}", method = RequestMethod.GET)
    public Response getUserById(@PathVariable String id) {
        User user = userService.get(id);
        if (user == null) {
            return new Response.Builder().setMessage("no data found").setStatus(404).build();
        }
        return new Response.Builder().setMessage("ok").setStatus(200).setData(user).build();
    }
}

至此,Swagger2的简单配置就完成了。

 

三、测试

(一)Druid监控

在Druid的监控设置中,我们将监控平台的路径设置为/druid/,下面让我们看一看监控平台的样子,访问监控页面需要输入用户名和密码,这是我们先前配置的,进入监控平台后的页面如下:

SpringBoot 整合 Mybatis + Druid + Swagger2

在*导航栏中我们看到Druid监控平台的主要功能,具体的监控功能还需要进一步学习。

需要指出的是,Druid监控平台是基于内存数据的,在我们使用的过程中需要根据需要进行监控数据的持久化。

(二)日志记录

我们在log4j2.xml中配置了日志的记录方式,将日志文件保存在./logs/下,在项目目录下会生成一个logs文件夹,其中按月份组织日志文件,如下所示:

SpringBoot 整合 Mybatis + Druid + Swagger2

其中druid-sql.log是我们设置的druid sql执行记录,部分内容如下:

[2018-07-12 18:45:18] DEBUG 137 statementLog - {conn-10005, pstmt-20001} executed. SELECT
         
        a.id AS "id",
        a.name AS "name"
     
        FROM user a
[2018-07-12 18:46:11] DEBUG 137 statementLog - {conn-10005, pstmt-20000} executed. SELECT
         
        a.id AS "id",
        a.name AS "name"
     
        FROM user a
[2018-07-12 18:53:27] DEBUG 137 statementLog - {conn-10005, pstmt-20000} executed. SELECT
         
        a.id AS "id",
        a.name AS "name"
     
        FROM user a
[2018-07-12 18:53:58] DEBUG 137 statementLog - {conn-10005, pstmt-20000} executed. SELECT
         
        a.id AS "id",
        a.name AS "name"
     
        FROM user a

(三)在线API文档

界面如下图所示:

SpringBoot 整合 Mybatis + Druid + Swagger2

这里不仅可以查看配置的接口信息,而且可以用于测试接口,我们以/user/list为例进行测试

SpringBoot 整合 Mybatis + Druid + Swagger2

测试结果如下:

SpringBoot 整合 Mybatis + Druid + Swagger2

这里的返回结果是进行了封装了统一相应格式,具体的实现请参考源码。

四、总结

SpringBoot为我们提供了简洁的配置方式,可以让开发人员更注重业务的实现。

Druid由阿里开源,是非常优秀的Java数据库连接池,而且具有很强的监控功能,值得我们深入学习。

Swagger2为我们提供了一个简单的在线API文档平台,而且可以进行接口测试,是后端人员的福利工具。

经过一番配置和测试,我们最终完成了SpringBoot整合Mybatis、Druid和Swagger2,搭建了数据源监控、日志记录以及在线Api文档平台,这个项目作为学习的开端,也将会作为以后学习过程中使用的种子项目。

最后,附上源码:https://github.com/GreedyStar/SpringBootDemo/tree/sample-1

SQL就不贴出来了,user表只包含id和name。

最后的最后,安利一下自己写的一个Java代码生成工具,能够方便的生成Spring、SpringMVC、Mybatis架构下的Java代码,希望能对大家有所帮助,地址:Java代码生成器:Generator

 

欢迎关注技术公众号:架构师成长营

SpringBoot 整合 Mybatis + Druid + Swagger2