在我们的日常开发中,数据库操作最多的就是通过Mybatis做ORM框架,Druid做数据源连接工具。之前在工作中,实际使用SpringBoot开发的场景并不是很多,以至于在这方面的整合没有积累经验。鉴于最近自己的项目需要支持SpringBoot,故借此机会,将这两个框架和SpringBoot做一个快速整合。
废话不多说,开始上代码~
初始化Spring Boot工程的方式有多种,可以通过 https://start.spring.io/ 或者 idea 创建;因为是一个整合教程,我这次选择纯手工创建一个Spring Boot工程。
整体工程是标准的Maven结构,如下:
lizard-data-admin
|-src
|-main
|-java
|-io.lizardframework.data.admin
|-configuration
|-DataSourceConfiguration.java
|-LizardDataAdminApplication.java
|-resources
|-mapper
|-LizardDataServiceEntityMapper.xml
|-application.properties
|-log4j2.xml
|-test
|-pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.5.RELEASEversion>
<relativePath/>
parent>
<groupId>io.lizardframework.data.admingroupId>
<artifactId>lizard-data-adminartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>lizard-data-adminname>
<description>Lizard Data Project Admindescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.16version>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.0.1version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
从pom文件中我们可以看出,我们使用了druid和mybatis的spring-boot-start。为什么?
在最开始整合的时候,我个人也认为,SpringBoot的start让我失去了对工程Bean的控制力,同时也纠结过同样的创建DataSource,到底是start先初始化,还是我的@Bean先初始化?
翻阅官方文档,发现这么一句话:
Auto-configuration is non-invasive. At any point, you can start to define your own configuration to replace specific parts of the auto-configuration. For example, if you add your own DataSource bean, the default embedded database support backs away.
简单来说,就是你自己定义的配置,会替换掉auto-config的配置,所以我们无需太多关心。
使用官方提供的starter可以让我们快速完成整合配置,并可以在适当的时候,进行一些高级别的编程,来实现我们自定义的需求。(这块先按下不表,未来单独来说~)
本文默认你已经有一点Spring Boot基础,知道一些基础的SpringBoot配置属性。
在上一节中,我们完成了pom文件的编写,将最基本的依赖已经引入到我们的工程中。现在,我们要配置application.properties文件,添加druid和mybatis的配置:
# application config
spring.application.name=lizard-data-admin
server.port=8080
# datasource pool config
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/lizard_data?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.platform=mysql
spring.datasource.username=root
spring.datasource.password=root
# 初始化连接池连接数
spring.datasource.druid.initial-size=3
# 连接池最小活跃数
spring.datasource.druid.min-idle=3
# 连接池最大连接数
spring.datasource.druid.max-active=15
# 获取连接等待超时时间
spring.datasource.druid.max-wait=5000
# 间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=90000
# 一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.druid.min-evictable-idle-time-millis=1800000
# 获取时检测
spring.datasource.druid.test-on-borrow=false
# 归还时检测
spring.datasource.druid.test-on-return=false
# 空闲检测
spring.datasource.druid.test-while-idle=true
# mybatis config
# Mapper文件路径
mybatis.mapper-locations=classpath:mapper/**/*.xml
这套配置在之前公司一直应用在生产环境,整体较为稳定。大家可以根据自己的实际情况来修改连接数。
经过上面的步骤,文件配置阶段基本结束。我们需要编写SpringBoot配置类
路径:io.lizardframework.data.admin.configuration.DataSourceConfiguration
@Configuration
@EnableTransactionManagement // 一定要开启 支持@Transactional注解
@MapperScan(basePackages = "io.lizardframework.data.admin.dao", annotationClass = Repository.class) // Mybatis-Spring扫描Dao接口路径和扫描指定注解的类,类似于xml中配置MapperScannerConfigurer bean的属性
public class DataSourceConfiguration {
/**
* 创建数据源
*
* @return
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean(name = "dataSource")
@Primary
public DataSource createDataSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* 创建事务管理器
*
* @param dataSource
* @return
*/
@Bean("transactionManager")
public PlatformTransactionManager createTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
上面的章节,我们说过Springboot的auto-config会自动回退,将Mybatis的Mapper文件和Dao接口存放在配置的路径中。
为了验证自动回退机制是否生效,我们在druid-spring-boot-start和spring-boot-autoconfigure-2.1.5.RELEASE中,对DataSource进行初始化的自动配置类中,打入断点,观察启动时是否会执行:
@Configuration
@ConditionalOnClass({DruidDataSource.class})
@AutoConfigureBefore({DataSourceAutoConfiguration.class})
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class, DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {
private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);
public DruidDataSourceAutoConfigure() {
}
@Bean(
initMethod = "init"
)
@ConditionalOnMissingBean
public DataSource dataSource() {
// 在日志处断点
LOGGER.info("Init DruidDataSource");
return new DruidDataSourceWrapper();
}
}
@Configuration
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"}
)
static class Generic {
Generic() {
}
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
启动SpringBoot工程的Main方法,LizardDataAdminApplication.java:
@SpringBootApplication
public class LizardDataAdminApplication {
public static void main(String[] args) {
SpringApplication.run(LizardDataAdminApplication.class, args);
}
}
我们观察启动过程,直接进入到我们自定义的DatsSource的@Bean中:
观察启动日志:
没有DruidDataSourceAutoConfigure match的条件,因为我们已经创建了DataSource。所以,自动配置回退。
至此,整合完成。我们可以按照自己的编码习惯,编写Service和Controller,来测试是否OK。
可能会有人好奇,上面的启动debug日志是如何打印的。我个人推荐使用log4j2作为日志框架,好处很多,可以百度。我们同样以starter的方式引入:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
<exclusions>
<exclusion>
<artifactId>*artifactId>
<groupId>*groupId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-log4j2artifactId>
dependency>
dependencies>
修改log4j2.xml文件:
<configuration>
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout charset="UTF-8" pattern="[%-5p] %d %c - %m%n"/>
Console>
Appenders>
<Loggers>
<root level="debug">
<AppenderRef ref="CONSOLE"/>
root>
Loggers>
configuration>
在本例中,我们简单的将日志输出到控制台。修改level,即可输出不同级别的日志。