环境准备:
开发规范——接口文档
开发规范-Restful
描述一个网络资源有两种方式,一种是传统风格
还有一种是Rest风格
在Rest风格中会根据不同请求方式执行不同的操作,如上图的四种不同的请求分别对应了四种不同的操作。
注意事项:
开发规范——统一响应结果
开发流程
日志信息记录——lombok的注解记录日志
原始方法记录日志(定义一个的Logger对象):
private static Logger log = LoggerFactory.getLogger(DeptController.class); //记录日志 log.info("查询全部部门数据");
使用注解@Slf4j可以直接调用log.info,不用再创建一个Logger对象了,加上这段注解后会自动生成一个log变量就是上面的那句语句的作用。
部门管理部分
资源的请求方法限定
在注解@RequestMapping当中有一个method属性用于指定请求方式,如果不指定的话会默认不同的请求方式都可以调用@RequestMapping下的方法,同时又有一个衍生注解@GetMapping,就是直接指定了会响应的请求方式,同时不同的请求方式就有不同的@XXXMappering注解。
@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {
//private static Logger log = LoggerFactory.getLogger(DeptController.class);
@Autowired
private DeptService deptService;
/**
* 查询部门数据
* @return
*/
//@RequestMapping(value = "/depts",method = RequestMethod.GET) //指定请求方式为GET
@GetMapping
public Result list(){
log.info("查询全部部门数据");
//调用service查询部门数据
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
* @return
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id){
log.info("根据id删除部门:{}",id);
//调用service删除部门
deptService.delete(id);
return Result.success();
}
/**
* 新增部门
* @return
*/
@PostMapping
public Result add(@RequestBody Dept dept){
log.info("新增部门: {}" , dept);
//调用service新增部门
deptService.add(dept);
return Result.success();
}
}
向上面代码所示的一样,在一个Controller外面加上@RequestMapping注解并设置公共的访问路径之后,对于里面不同的资源根据需求再决定要不要设置路径。这样就是Rest风格,对于有需要传参的资源就使用一个@PathVariable注解获取url当中的参数,对于Post请求和Put请求则是使用@RequestBody注解把藏在请求体当中的信息截取出来
@RestController注解加上一个pojo成中的一个Result对象,就可以规定Controller当中所有响应数据都以JSON的格式传递回去。
前端工程依托于nginx运行,在前端页面里面有一个发送请求表单用于获取后端数据
自行实现的查询接口(重点)
首先第一步,跳过需求分析直接查看接口文档看要怎么实现
响应数据样式
看完接口文档之后确定要实现一个GET请求的接口方法根据传进来的id进行查询并将数据以JSON的格式进行返回。
第一步:在Mapper层声明一个根据id查询的方法
此处返回值就是查询的结果数据类型
@Select("select * from dept where id=#{id}")
Dept selectById(Integer id);
第二步:在service层实现一个 方法专门用于调用Mapper层中的查询语句
此处要先创建一个Mapper层的对象,才能调用方法
@Autowired
private DeptMapper deptMapper;
@Override
public Dept selectById(Integer id)
{
return deptMapper.selectById(id);
}
第三步:在Controller层中声明对应的方法,这里同样要先获取一个service层的对象才可以使用service中的方法,此处controller返回给前端的是一个包装好JSON类型的对象。
@Autowired
private DeptService deptService;
@GetMapping("/{id}")
public Result selectById(@PathVariable Integer id) {
log.info("查询实现:", id);
Dept dept=deptService.selectById(id);
return Result.success(dept);
}
自行实现的更新接口(重点)
查看接口文档
第一步:在Mapper层创建对应的SQL语句接口
@Update("update dept set name=#{name},update_time=#{updateTime} where id=#{id}")
void update(Dept dept);
注意,此处的update_time写成updateTime会出现以下错误,原因是数据库表当中没有updateTime这个属性,因为在表中是update_time这个格式的,只是在idea中使用时要变成updateTime,用驼峰命名法使用。
第二步:在service层创建对应的update方法调用Mapper层中的方法,同时,要改变另一个属性的值,就是updateTime,要根据当下时间注入,。
@Override
public void update(Dept dept)
{
dept.setUpdateTime(LocalDateTime.now());
deptMapper.update(dept);
}
第三步:在controller层创建对应的资源方法,并设定请求方式为Put,同时根据接口文档在请求体里面接收一个dept对象,同时调用update里面的方法。
@PutMapping
public Result update(@RequestBody Dept dept)
{
log.info("更新实现",dept);
deptService.update(dept);
return Result.success();
}
前端测试结果成功
点击编辑时先显示原本的数据,更改后显示新的数据
————————————————————————————
员工管理部分
要实现如 下图的一个分页信息显示要用到分页查询
需要后端返回的就两个,一个是分页查询返回的结果,还有一个是下面的总记录数500,右边的页数跳转可以根据总记录数除以每页展示记录数向上取整即可
分页查询
-- 分页查询语法
-- 参数1: 起始索引=(页码-1)* 每页展示记录数
-- 参数2: 查询返回记录数=每页展示记录数
select * from Emp limit 0,5;
-- 查询第二页数据,每页展示5条数据
select * from Emp limit 5,5;
-- 查询第三页数据,每页展示5条数据
select * from Emp limit 10,5;
-- 获取总记录数
select count(*) from emp;
参数分析
接口文档分析
三层架构代码分析
Mapper层代码实现
@Select("select count(*) from emp")
public Long count();
@Select("select * from emp limit #{start},#{pageSize}")
public List<Emp> page(Integer start, Integer pageSize);
Controller层代码实现
根据接口文档里面的路径
@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);
}
Service层代码实现
@Override
public PageBean page(Integer page, Integer pageSize) {
//1. 获取总记录数
Long count = empMapper.count();
//2. 获取分页查询结果列表
Integer start = (page - 1) * pageSize;
List<Emp> empList = empMapper.page(start, pageSize);
//3. 封装PageBean对象
PageBean pageBean = new PageBean(count, empList);
return pageBean;
}
使用postman进行测试
前端测试
分页插件 PageHepler
引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.2</version>
</dependency>
使用分页插件后可以依旧是原本的查询语句并且但是达到分页查询的效果。
先是设置分页参数,查询时分页插件会自动帮忙实现两个查询。
查询后返回的是一个封装好的Page类型,使用类型强转将查询结果转为Page类型
条件分页查询
使用动态SQL实现
根据接口文档可以如下实现
Controller层代码变成
其中涉及到时间传递的,使用一个@DateTimeFormat注解进行格式的限定
@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);
//调用service分页查询
PageBean pageBean = empService.page(page, pageSize, name, gender, begin, end);
return Result.success(pageBean);
}
Service层修改为
@Override
public PageBean page(Integer page, Integer pageSize,String name, Short gender,LocalDate begin,LocalDate end) {
//1. 设置分页参数
PageHelper.startPage(page,pageSize);
//2. 执行查询
List<Emp> empList = empMapper.list(name, gender, begin, end);
Page<Emp> p = (Page<Emp>) empList;
//3. 封装PageBean对象
PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
return pageBean;
}
Mapper层改为
去掉注解,使用XML映射文件配置Mapper
public List<Emp> list(String name, Short gender,LocalDate begin,LocalDate end);
在resources目录下保持和Mapper接口文件相同的目录
内容如下
其中resultType是单条记录封装的类型,其余where标签和if标签的使用和之前一样,
下面里name要既不等于null也要不等于""才行,不然为""时也会拼接上SQL语句里面
<?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.example.mapper.EmpMapper">
<!--条件查询-->
<select id="list" resultType="com.example.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>
postman测试
虽然显示500错误,但是控制台已经输出了查询结果
前端页面成功显示
分页查询插件的大坑
但是我这里的是另外一种错误,是因为springboot版本过高,插件没赶上时代,解决方案
——————————————————————————
删除员工
单个删除是一个特殊的批量删除
接口文档
操作步骤
Mapper.xml当中
这里使用一个foreach标签
<delete id="delete">
delete
from emp
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
service当中
@Override
public void delete(List<Integer> ids) {
empMapper.delete(ids);
}
Controller层当中 ,因为要传参数,放在请求体里面
@DeleteMapping("/{ids}")
public Result delete(@PathVariable List<Integer> ids){
log.info("批量删除操作, ids:{}",ids);
empService.delete(ids);
return Result.success();
}
新增员工
需求分析
接口文档
流程思路实现
Controller层实现
此处使用的@RequestBody注解将请求体当中的JSON数据封装到一个Emp实体类当中的前提是,实体类里面有着和JSON数据里面相同的属性名和属性类型
@PostMapping
public Result save(@RequestBody Emp emp)
{
log.info("新增员工:emp"+emp);
empService.save(emp);
return Result.success();
}
Mapper层实现
@Insert("insert into emp emp(username,name,gender,image,job,entrydate,dept_id,create_time,update_time)" +
"values(#{usernmae},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
void insert(Emp emp);
Service层实现
@Override
public void save(Emp emp) {
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
empMapper.insert(emp);
}
postman测试成功输出
前端测试
添加员工
——————————————————————————
下面的内容还有文件上传,员工更新,以及配置文件都在另一个文章里面
链接如下:】