前面博文我们创建了springboot工程,处理了http请求,处理了属性的依赖注入和http请求的参数解析,那么一个基本的springboot工程已经搭建好了。现在来尝试springboot与持久层的集成,使用mybatis框架。
提前安装好mysql以备调试,参考教程:
提前下载好mybatis自动生成工具,参考教程:
提前创建用户、数据库、table。然后开始集成mybatis。
一、修改pom.xml文件,添加必要的依赖
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<groupId>com.test2</groupId>
<artifactId>qftest2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>qftest2</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 想要配置log4j2,就要先去除logging包 -->
<exclusions>
<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>
<!-- 添加log4j2依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- json所有依赖jar包 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>net.sf.ezmorph</groupId>
<artifactId>ezmorph</artifactId>
<version>1.0.3</version>
</dependency>
<!-- 热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 没有该配置,devtools 不生效 -->
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
直接放出文件源码,我的每处修改都加了备注,供参考。自动下载依赖包需要时间,等吧。依赖的jar包版本要留意,错了真的可能报错,排查要好久。springboot是2.0版本一定要留意,如果一定要用springboot1.5版本的化,请参考这个博文 写的很详细。
二、修改配置文件:
添加mybatis需要的必要配置,由于配置较多,建议直接更换配置文件,删除原application.properties文件,新增application.yml配置文件。还是直接放出代码供参考吧,错一点就跑不起来。
server:
port: 8081
servlet:
context-path: /qftest
tomcat:
uri-encoding: UTF-8
#logging:
#config: src/main/resources/mapping/log4j2.xml
spring:
profiles:
active: dev
http:
encoding:
charset: UTF-8
enabled: true
force: true
messages:
encoding: UTF-8
datasource:
name: test
type: com.alibaba.druid.pool.DruidDataSource
#druid相关配置
druid:
#监控统计拦截的filters
filters: stat
driver-class-name: com.mysql.jdbc.Driver
#基本属性
url: jdbc:mysql://127.0.0.1:3306/testdb1?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
username: qftest1
password: Pass@word
#配置初始化大小/最小/最大
initial-size: 1
min-idle: 1
max-active: 20
#获取连接等待超时时间
max-wait: 60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
#一个连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
##
mybatis:
mapper-locations: classpath:mapping/*.xml #注意:一定要对应mapper映射xml文件的所在路径
type-aliases-package: com.test2.qftest2.model # 注意:对应实体类的路径
其中,spring.profiles.active 属性依然是将生产环境和开发环境配置分离。仔细看我前面的博文应该会发现,我的log4j2配置文件中生产环境和测试环境输出地址是分开配置的,但是都写在了log4j2配置文件里,上线前打包工程的时候要留意修改,不然会报错。那么今天就注释掉application.yml中关于log4j2的配置,改为在application-dev和-prod中分开配置。同时log4j2配置文件也拆分成log4j2-dev和log4j2-prod两个不同的版本。
application-dev.properties内容
test.testinfo = 调用dev.properties信息成功
logging.config: classpath:log4j2-dev.xml
application-prod.properties内容
test.testinfo = 调用prod.properties信息成功
logging.config: classpath:log4j2-prod.xml
log4j2-dev.xml内容
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<properties>
<!-- 文件输出格式 -->
<property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} |-%-5level [%thread] %c [%L] -| %msg%n</property>
<!--设置日志在硬盘上输出的目录-->
<!-- 相对路径配置,日志会存放在项目根目录下,依据相对路径创建文件夹 -->
<property name="logPath">log</property><!-- 开发时强烈建议相对路径,好找。 绝对路径受操作系统限制,而且本地开发环境下真的分不清是哪个项目记的。。。-->
<!-- 绝对路径配置,日志会存放指定的绝对路径下 -->
<!--<property name="logPath">D:/log</property>--><!-- 生产环境发布时建议按项目要求设置绝对路径-->
</properties>
<appenders>
<Console name="CONSOLE" target="system_out">
<PatternLayout pattern="${PATTERN}" />
</Console>
<!--设置级别为INFO日志输出到info.log中-->
<RollingFile name="INFO" filename="${logPath}/info.log"
filepattern="${logPath}/%d{YYYYMMdd}-%i-info.log.zip">
<Filters>
<!--设置只输出级别为INFO的日志-->
<ThresholdFilter level="INFO"/>
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="[ %-5p]:%d{YYYY-MM-dd HH:mm:ss} [%t] %c{1}:%L - %msg%n" />
<Policies>
<!--设置每天打包日志一次-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!--设置日志文件满1MB后打包-->
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
<!--设置级别为WARN日志输出到warn.log中-->
<RollingFile name="WARN" filename="${logPath}/warn.log"
filepattern="${logPath}/%d{YYYYMMdd}-%i-warn.log.zip">
<Filters>
<!--设置只输出级别为WARN的日志-->
<ThresholdFilter level="WARN"/>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="[ %-5p]:%d{YYYY-MM-dd HH:mm:ss} [%t] %c{1}:%L - %msg%n" />
<Policies>
<!--设置每天打包日志一次-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!--设置日志文件满1MB后打包-->
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
<!--设置级别为ERROR日志输出到error.log中-->
<RollingFile name="ERROR" filename="${logPath}/error.log"
filepattern="${logPath}/%d{YYYYMMdd}-%i-error.log.zip">
<!--设置只输出级别为ERROR的日志-->
<ThresholdFilter level="ERROR"/>
<PatternLayout pattern="[ %-5p]:%d{YYYY-MM-dd HH:mm:ss} [%t] %c{1}:%L - %msg%n" />
<Policies>
<!--设置每天打包日志一次-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!--设置日志文件满1MB后打包-->
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
<!--设置级别为DEBUG日志输出到debug.log中-->
<RollingFile name="DEBUG" filename="${logPath}/debug.log"
filepattern="${logPath}/%d{YYYYMMdd}-%i-debug.log.zip">
<!--设置只输出级别为DEBUG的日志-->
<Filters>
<ThresholdFilter level="DEBUG"/>
<ThresholdFilter level="INFO" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="[ %-5p]:%d{YYYY-MM-dd HH:mm:ss} [%t] %c{1}:%L - %msg%n" />
<Policies>
<!--设置每天打包日志一次-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!--设置日志文件满1MB后打包-->
<SizeBasedTriggeringPolicy size="1 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
<!--设置通过邮件发送日志信息-->
<!--
<SMTP name="Mail" subject="XXXXSaaS系统正式版异常信息" to="yong.shi@lengjing.info" from="message@lengjing.info"
smtpUsername="message@lengjing.info" smtpPassword="LENG****1234" smtpHost="mail.lengjing.info" smtpDebug="false"
smtpPort="25" bufferSize="10">
<PatternLayout pattern="[%-5p]:%d{YYYY-MM-dd HH:mm:ss} [%t] %c{1}:%L - %msg%n" />
</SMTP>
-->
</appenders>
<Loggers>
<logger name="com.test2.qftest2" level="INFO" additivity="true">
<appender-ref ref="INFO" />
<appender-ref ref="WARN" />
<appender-ref ref="ERROR" />
<appender-ref ref="DEBUG" />
<!--<appender-ref ref="Mail" />-->
</logger>
<!--<root level="DEBUG">--><!-- debug信息实在是太多了,不想看 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</Loggers>
</configuration>
log4j2-prod.xml只是把<property name="logPath">标签内容修改一下,就不粘源码了。
三、使用mybatis工具生成model、mapper、mapping代码
具体参考我的教程
教程里的示例table就是现在要用的,创建好的src目录下的代码也可以拷贝过来。注意为教程中的文件结构配置是图简便设置的,粘贴的时候要仔细检查下,个人建议还是按照你工程中的实际文件结构配置mybatis代码生成工具的xml配置文件,不然生成的代码里,要改好多东西,昨晚的痛苦经历不忍回忆。。。
粘好的程序结构如下图所示
mapping文件夹请留意,里面放的是dao层的sql代码,都是xml文件,我整体放在resources下了。application.yml中mybatis的配置指定mapper-locations时一定要指向这个mapping包,而且这个mapping包里千万不要放别的配置文件,比如log4j2.xml。。。
为了方便测试,对生成的代码添加点功能,主要是为了试试分页查询。
UserMapper.java中添加函数
List<User> selectAllUser();
UserMapper.xml中添加配置
<select id="selectAllUser" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_user
</select>
四、创建controller和service
创建controller、service、service.impl文件夹、创建UserController类、UserService、UserServiceImpl类。
UserController类源码
package com.test2.qftest2.controller;
import com.test2.qftest2.model.User;
import com.test2.qftest2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserService userService;
@ResponseBody
@RequestMapping(value = "/add", produces = {"application/json;charset=UTF-8"})
public int addUser(User user){
return userService.addUser(user);
}
@ResponseBody
@RequestMapping(value = "/all/{pageNum}/{pageSize}", produces = {"application/json;charset=UTF-8"})
public Object findAllUser(@PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize){
return userService.findAllUser(pageNum,pageSize);
}
}
UserService类源码
package com.test2.qftest2.service;
import com.test2.qftest2.model.User;
import java.util.List;
public interface UserService {
int addUser(User user);
List<User> findAllUser(int pageNum, int pageSize);
}
UserServiceImpl类源码
package com.test2.qftest2.service.impl;
import com.github.pagehelper.PageHelper;
import com.test2.qftest2.mapper.UserMapper;
import com.test2.qftest2.model.User;
import com.test2.qftest2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service(value = "userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;//这里会报错,但是并不会影响
@Override
public int addUser(User user) {
return userMapper.insertSelective(user);
}
/*
* 这个方法中用到了我们开头配置依赖的分页插件pagehelper
* 很简单,只需要在service层传入参数,然后将参数传递给一个插件的一个静态方法即可;
* pageNum 开始页数
* pageSize 每页显示的数据条数
* */
@Override
public List<User> findAllUser(int pageNum, int pageSize) {
//将参数传给这个方法就可以实现物理分页了,非常简单。
PageHelper.startPage(pageNum, pageSize);
return userMapper.selectAllUser();
}
}
创建好的程序结构如下图所示
其中UserServiceImpl.java类中,private UserMapper userMapper会报错,如果实在强迫症受不了的化参考下图处理。
至此,springboot集成mybatis配置完成。编译运行后可使用postman工具进行测试
当然了,编译运行的过程中会遇到很多异常,踩很多坑, 只能根据情况一点一点排查了。