一、准备工作
1. 环境搭建

步骤:
-
准备数据库表(dept、emp)
-
创建springboot工程,引入对应的起步依赖(web、mybatis、mysql驱动、lombok)
-
配置文件application.properties中引入mybatis的配置信息,准备对应的实体类
-
准备对应的Mapper、Service(接口、实现类)、Controller基础结构
2. 开发规范
(1) 基于REST风格URL
bash
http://localhost:8080/users/1 GET:查询id为1的用户
http://localhost:8080/users POST:新增用户
http://localhost:8080/users PUT:修改用户
http://localhost:8080/users/1 DELETE:删除id为1的用户
总结:通过URL定位要操作的资源,通过HTTP动词(请求方式)来描述具体的操作。
(2) 在REST风格的URL中,通过四种请求方式,来操作数据的增删改查。
-
GET : 查询
-
POST :新增
-
PUT :修改
-
DELETE :删除
注意事项:
① REST是风格,是约定方式,约定不是规定,可以打破
② 描述模块的功能通常使用复数,也就是加s的格式来描述,表示此类资源,而非单个资源。如:users、emps、books...
3. 功能开发
(1) 需求
请求路径:/depts
请求方式:GET
请求参数:无
响应数据:json格式
(2) 代码实现
DeptController:
java
@Slf4j
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
//@RequestMapping(value = "/depts" , method = RequestMethod.GET)
@GetMapping("/depts")
public Result list(){
log.info("查询所有部门数据");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
}
① @GetMapping 是 Spring 为了简化代码提供的 "语法糖"(简化写法),它本质上就是 @RequestMapping 限定了 method = RequestMethod.GET 的结果,使用 @GetMapping 会让代码更简洁、可读性更高。
② @Slf4j注解源码:

DeptService(业务接口)
java
public interface DeptService {
/**
* 查询所有的部门数据
* @return 存储Dept对象的集合
*/
List<Dept> list();
}
DeptServiceImpl(业务实现类)
java
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> list() {
List<Dept> deptList = deptMapper.list();
return deptList;
}
}
DeptMapper
java
@Mapper
public interface DeptMapper {
//查询所有部门数据
@Select("select id, name, create_time, update_time from dept")
List<Dept> list();
}
二、删除部门
1. 需求
- 请求路径:/depts/{id}
- 请求方式:DELETE
- 接口描述:该接口用于根据ID删除部门数据
2. 思路分析
Q1:怎么在controller中接收请求路径中的路径参数?
A1:@PathVariable
Q2:如何限定请求方式是delete?A2:@DeleteMapping
3. 代码实现
DeptController
java
@Slf4j
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@DeleteMapping("/depts/{id}")
public Result delete(@PathVariable Integer id) {
//日志记录
log.info("根据id删除部门");
//调用service层功能
deptService.delete(id);
//响应
return Result.success();
}
//省略...
}
DeptService(接口)
java
public interface DeptService {
/**
* 根据id删除部门
* @param id 部门id
*/
void delete(Integer id);
//省略...
}
DeptServiceImpl(实现类)
java
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public void delete(Integer id) {
//调用持久层删除功能
deptMapper.deleteById(id);
}
//省略...
}
DeptMapper
java
@Mapper
public interface DeptMapper {
/**
* 根据id删除部门信息
* @param id 部门id
*/
@Delete("delete from dept where id = #{id}")
void deleteById(Integer id);
//省略...
}
三、新增部门
1. 思路分析
Q1:如何限定请求方式是POST?
A1:@PostMapping
Q2:怎么在controller中接收json格式的请求参数?A2:@RequestBody //把前端传递的json数据填充到实体类中
2. 代码实现
DeptController
java
@Slf4j
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/depts")
public Result add(@RequestBody Dept dept){
//记录日志
log.info("新增部门:{}",dept);
//调用service层添加功能
deptService.add(dept);
//响应
return Result.success();
}
//省略...
}
DeptService
java
public interface DeptService {
/**
* 新增部门
* @param dept 部门对象
*/
void add(Dept dept);
//省略...
}
DeptServiceImpl
java
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public void add(Dept dept) {
//补全部门数据
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
//调用持久层增加功能
deptMapper.inser(dept);
}
//省略...
}
DeptMapper
java
@Mapper
public interface DeptMapper {
@Insert("insert into dept (name, create_time, update_time) values (#{name},#{createTime},#{updateTime})")
void inser(Dept dept);
//省略...
}
3. 请求路径
(1) 首先我们先来看下目前controller层代码:

以上三个方法上的请求路径,存在一个共同点:都是以/depts作为开头。(重复了)
(2) 在Spring当中为了简化请求路径的定义,可以把公共的请求路径,直接抽取到类上,在类上加一个注解@RequestMapping,并指定请求路径"/depts"。代码参照如下:

注意事项:一个完整的请求路径,应该是类上@RequestMapping的value属性 + 方法上的 @RequestMapping的value属性
四、员工管理
1. 分页查询
(1) 代码实现
① PageBean
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private Long total; //总记录数
private List rows; //当前页数据列表
}
② EmpController
java
import com.itheima.pojo.PageBean;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
@Autowired
private EmpService empService;
//条件分页查询
@GetMapping
public Result page(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize) {
//记录日志
log.info("分页查询,参数:{},{}", page, pageSize);
//调用业务层分页查询功能
PageBean pageBean = empService.page(page, pageSize);
//响应
return Result.success(pageBean);
}
}
③ EmpService(接口定义方法,但不定义具体怎么做)
java
public interface EmpService {
/**
* 条件分页查询
* @param page 页码
* @param pageSize 每页展示记录数
* @return
*/
PageBean page(Integer page, Integer pageSize);
}
④ EmpServiceImp(实现类重写接口的方法,定义具体怎么做)
java
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Emp;
import com.itheima.pojo.PageBean;
import com.itheima.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.List;
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public PageBean page(Integer page, Integer pageSize) {
//1、获取总记录数
Long count = empMapper.count();
//2、获取分页查询结果列表
Integer start = (page - 1) * pageSize; //计算起始索引 , 公式: (页码-1)*页大小
List<Emp> empList = empMapper.list(start, pageSize);
//3、封装PageBean对象
PageBean pageBean = new PageBean(count , empList);
return pageBean;
}
}
EmpMapper
java
@Mapper
public interface EmpMapper {
//获取总记录数
@Select("select count(*) from emp")
public Long count();
//获取当前页的结果列表
@Select("select * from emp limit #{start}, #{pageSize}")
public List<Emp> list(Integer start, Integer pageSize);
}
(2) 分页插件
当使用了PageHelper分页插件进行分页,就无需再Mapper中进行手动分页了。 在Mapper中我们只需要进行正常的列表查询即可。在Service层中,调用Mapper的方法之前设置分页参数,在调用Mapper方法执行查询之后,解析分页结果,并将结果封装到PageBean对象中返回。
① 代码实现
1). 在pom.xml引入依赖
XML
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
2). EmpMapper
java
@Mapper
public interface EmpMapper {
//获取当前页的结果列表
@Select("select * from emp")
public List<Emp> list;
}
3). EmpServiceImpl
java
@Override
public PageBean page(Integer page, Integer pageSize) {
// 设置分页参数
PageHelper.startPage(page, pageSize);
// 执行分页查询
List<Emp> empList = empMapper.list();
// 获取分页结果
Page<Emp> p = (Page<Emp>) empList;
//封装PageBean
PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
return pageBean;
}
2. 分页查询(带条件)
(1) 代码实现
① EmpController
java
@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
@Autowired
private EmpService empService;
//条件分页查询
@GetMapping
public Result page(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
//记录日志
log.info("分页查询,参数:{},{},{},{},{},{}", page, pageSize,name, gender, begin, end);
//调用业务层分页查询功能
PageBean pageBean = empService.page(page, pageSize, name, gender, begin, end);
//响应
return Result.success(pageBean);
}
}
@DateTimeFormat是 SpringMVC 提供的参数格式化注解 ,核心解决前端字符串类型的日期 与后端 Java 日期类型(如 LocalDate/LocalDateTime) 的自动类型转换问题 ------ 简单说,就是让 Spring 能把前端传的yyyy-MM-dd格式字符串(如2026-01-29),自动转换成后端方法形参中LocalDate类型的对象,无需你手动写代码做字符串转日期的处理。括号里的大小写是固定的!- 年份:
y(公历年)/Y(周年) - 月份:
M(月份)/m(分钟) - 日期:
d(月中日期)/D(年中天数) - 小时:
H(24 小时制)/h(12 小时制)
② EmpService
java
public interface EmpService {
/**
* 条件分页查询
* @param page 页码
* @param pageSize 每页展示记录数
* @param name 姓名
* @param gender 性别
* @param begin 开始时间
* @param end 结束时间
* @return
*/
PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);
}
③ EmpServiceImpl
java
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
//设置分页参数
PageHelper.startPage(page, pageSize);
//执行条件分页查询
List<Emp> empList = empMapper.list(name, gender, begin, end);
//获取查询结果
Page<Emp> p = (Page<Emp>) empList;
//封装PageBean
PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
return pageBean;
}
}
④ EmpMapper
java
@Mapper
public interface EmpMapper {
//获取当前页的结果列表
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
}
⑤ EmpMapper.xml
java
<?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="com.itheima.mapper.EmpMapper">
<!-- 条件分页查询 -->
<select id="list" resultType="com.itheima.pojo.Emp">
select * from emp
<where>
<if test="name != null and name != ''">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>
</mapper>
3. 删除员工
(1) 思路分析
问题1:怎么在controller中接收请求路径中的路径参数?
@PathVariable
问题2:在Mapper接口中,执行delete操作的SQL语句时,条件中的id值是不确定的是动态的,怎么实现呢?
Mybatis中的动态SQL:foreach
(2) 代码实现
① EmpController
java
@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
@Autowired
private EmpService empService;
//批量删除
@DeleteMapping("/{ids}")
public Result delete(@PathVariable List<Integer> ids){
empService.delete(ids);
return Result.success();
}
//条件分页查询
@GetMapping
public Result page(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
//记录日志
log.info("分页查询,参数:{},{},{},{},{},{}", page, pageSize,name, gender, begin, end);
//调用业务层分页查询功能
PageBean pageBean = empService.page(page, pageSize, name, gender, begin, end);
//响应
return Result.success(pageBean);
}
}
② EmpService
java
public interface EmpService {
/**
* 批量删除操作
* @param ids id集合
*/
void delete(List<Integer> ids);
//省略...
}
③ EmpServiceImpl
java
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public void delete(List<Integer> ids) {
empMapper.delete(ids);
}
//省略...
}
④ EmpMapper
java
@Mapper
public interface EmpMapper {
//批量删除
void delete(List<Integer> ids);
//省略...
}
⑤ EmpMapper.xml
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="com.itheima.mapper.EmpMapper">
<!--批量删除员工-->
<select id="delete">
delete from emp where id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
<!-- 省略... -->
</mapper>