湖北营销型网站建设价格,暴雪代理最新消息,wordpress如何改默认后台地址,包头seo优化SpringBootWeb案例
前面我们已经讲解了Web前端开发的基础知识#xff0c;也讲解了Web后端开发的基础(HTTP协议、请求响应)#xff0c;并且也讲解了数据库MySQL#xff0c;以及通过Mybatis框架如何来完成数据库的基本操作。 那接下来#xff0c;我们就通过一个案例#xf…SpringBootWeb案例
前面我们已经讲解了Web前端开发的基础知识也讲解了Web后端开发的基础(HTTP协议、请求响应)并且也讲解了数据库MySQL以及通过Mybatis框架如何来完成数据库的基本操作。 那接下来我们就通过一个案例来将前端开发、后端开发、数据库整合起来。 而这个案例呢就是我们前面提到的Tlias智能学习辅助系统。 在这个案例中前端开发人员已经将前端工程开发完毕了。 我们需要做的就是参考接口文档完成后端功能的开发然后结合前端工程进行联调测试即可。
完成后的成品效果展示 今天的主要内容如下 准备工作部门管理员工管理 下面我们就进入到今天的第1个内容准备工作的学习。
1. 准备工作
准备工作的学习我们先从需求和环境搭建开始入手。
1.1 需求环境搭建
1.1.1 需求说明
1、部门管理 部门管理功能开发包括
查询部门列表删除部门新增部门修改部门
2、员工管理 员工管理功能开发包括
查询员工列表(分页、条件)删除员工新增员工修改员工
1.1.2 环境搭建 步骤
准备数据库表(dept、emp)创建springboot工程引入对应的起步依赖web、mybatis、mysql驱动、lombok配置文件application.properties中引入mybatis的配置信息准备对应的实体类准备对应的Mapper、Service(接口、实现类)、Controller基础结构
第1步准备数据库表
-- 部门管理
create table dept(id int unsigned primary key auto_increment comment 主键ID,name varchar(10) not null unique comment 部门名称,create_time datetime not null comment 创建时间,update_time datetime not null comment 修改时间
) comment 部门表;
-- 部门表测试数据
insert into dept (id, name, create_time, update_time) values(1,学工部,now(),now()),(2,教研部,now(),now()),(3,咨询部,now(),now()), (4,就业部,now(),now()),(5,人事部,now(),now());-- 员工管理(带约束)
create table emp (id int unsigned primary key auto_increment comment ID,username varchar(20) not null unique comment 用户名,password varchar(32) default 123456 comment 密码,name varchar(10) not null comment 姓名,gender tinyint unsigned not null comment 性别, 说明: 1 男, 2 女,image varchar(300) comment 图像,job tinyint unsigned comment 职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师,entrydate date comment 入职时间,dept_id int unsigned comment 部门ID,create_time datetime not null comment 创建时间,update_time datetime not null comment 修改时间
) comment 员工表;
-- 员工表测试数据
INSERT INTO emp(id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time) VALUES(1,jinyong,123456,金庸,1,1.jpg,4,2000-01-01,2,now(),now()),(2,zhangwuji,123456,张无忌,1,2.jpg,2,2015-01-01,2,now(),now()),(3,yangxiao,123456,杨逍,1,3.jpg,2,2008-05-01,2,now(),now()),(4,weiyixiao,123456,韦一笑,1,4.jpg,2,2007-01-01,2,now(),now()),(5,changyuchun,123456,常遇春,1,5.jpg,2,2012-12-05,2,now(),now()),(6,xiaozhao,123456,小昭,2,6.jpg,3,2013-09-05,1,now(),now()),(7,jixiaofu,123456,纪晓芙,2,7.jpg,1,2005-08-01,1,now(),now()),(8,zhouzhiruo,123456,周芷若,2,8.jpg,1,2014-11-09,1,now(),now()),(9,dingminjun,123456,丁敏君,2,9.jpg,1,2011-03-11,1,now(),now()),(10,zhaomin,123456,赵敏,2,10.jpg,1,2013-09-05,1,now(),now()),(11,luzhangke,123456,鹿杖客,1,11.jpg,5,2007-02-01,3,now(),now()),(12,hebiweng,123456,鹤笔翁,1,12.jpg,5,2008-08-18,3,now(),now()),(13,fangdongbai,123456,方东白,1,13.jpg,5,2012-11-01,3,now(),now()),(14,zhangsanfeng,123456,张三丰,1,14.jpg,2,2002-08-01,2,now(),now()),(15,yulianzhou,123456,俞莲舟,1,15.jpg,2,2011-05-01,2,now(),now()),(16,songyuanqiao,123456,宋远桥,1,16.jpg,2,2007-01-01,2,now(),now()),(17,chenyouliang,123456,陈友谅,1,17.jpg,NULL,2015-03-21,NULL,now(),now());第2步创建一个SpringBoot工程选择引入对应的起步依赖web、mybatis、mysql驱动、lombok (版本选择2.7.5版本可以创建完毕之后在pom.xml文件中更改版本号) 生成的pom.xml文件
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.7.5/versionrelativePath/ /parentgroupIdcom.itheima/groupIdartifactIdtlias-web-management/artifactIdversion0.0.1-SNAPSHOT/versionnametlias-web-management/namedescriptionDemo project for Spring Boot/descriptionpropertiesjava.version11/java.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.3.0/version/dependencydependencygroupIdcom.mysql/groupIdartifactIdmysql-connector-j/artifactIdscoperuntime/scope/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationexcludesexcludegroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/exclude/excludes/configuration/plugin/plugins/build/project创建项目工程目录结构 第3步配置文件application.properties中引入mybatis的配置信息准备对应的实体类
application.properties 直接把之前项目中的复制过来
#数据库连接
spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver
spring.datasource.urljdbc:mysql://localhost:3306/tlias
spring.datasource.usernameroot
spring.datasource.password1234#开启mybatis的日志输出
mybatis.configuration.log-implorg.apache.ibatis.logging.stdout.StdOutImpl#开启数据库表字段 到 实体类属性的驼峰映射
mybatis.configuration.map-underscore-to-camel-casetrue实体类
/*部门类*/
Data
NoArgsConstructor
AllArgsConstructor
public class Dept {private Integer id;private String name;private LocalDateTime createTime;private LocalDateTime updateTime;
}/*员工类*/
Data
NoArgsConstructor
AllArgsConstructor
public class Emp {private Integer id;private String username;private String password;private String name;private Short gender;private String image;private Short job;private LocalDate entrydate;private Integer deptId;private LocalDateTime createTime;private LocalDateTime updateTime;
}第4步准备对应的Mapper、Service(接口、实现类)、Controller基础结构
数据访问层
DeptMapper
package com.itheima.mapper;
import org.apache.ibatis.annotations.Mapper;Mapper
public interface DeptMapper {
}EmpMapper
package com.itheima.mapper;
import org.apache.ibatis.annotations.Mapper;Mapper
public interface EmpMapper {
}
业务层
DeptService
package com.itheima.service;//部门业务规则
public interface DeptService {
}DeptServiceImpl
package com.itheima.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;//部门业务实现类
Slf4j
Service
public class DeptServiceImpl implements DeptService {
}EmpService
package com.itheima.service;//员工业务规则
public interface EmpService {
}EmpServiceImpl
package com.itheima.service.impl;
import com.itheima.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;//员工业务实现类
Slf4j
Service
public class EmpServiceImpl implements EmpService {}控制层
DeptController
package com.itheima.controller;
import org.springframework.web.bind.annotation.RestController;//部门管理控制器
RestController
public class DeptController {
}EmpController
package com.itheima.controller;
import org.springframework.web.bind.annotation.RestController;//员工管理控制器
RestController
public class EmpController {
}项目工程结构 1.2 开发规范
了解完需求也完成了环境搭建了我们下面开始学习开发的一些规范。
开发规范我们主要从以下几方面介绍
1、开发规范-REST
我们的案例是基于当前最为主流的前后端分离模式进行开发。 在前后端分离的开发模式中前后端开发人员都需要根据提前定义好的接口文档来进行前后端功能的开发。 后端开发人员必须严格遵守提供的接口文档进行后端功能开发保障开发的功能可以和前端对接 而在前后端进行交互的时候我们需要基于当前主流的REST风格的API接口进行交互。
什么是REST风格呢?
RESTRepresentational State Transfer表述性状态转换它是一种软件架构风格。
传统URL风格如下
http://localhost:8080/user/getById?id1 GET查询id为1的用户
http://localhost:8080/user/saveUser POST新增用户
http://localhost:8080/user/updateUser POST修改用户
http://localhost:8080/user/deleteUser?id1 GET删除id为1的用户我们看到原始的传统URL呢定义比较复杂而且将资源的访问行为对外暴露出来了。
基于REST风格URL如下
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动词(请求方式)来描述具体的操作。
在REST风格的URL中通过四种请求方式来操作数据的增删改查。
GET 查询POST 新增PUT 修改DELETE 删除
我们看到如果是基于REST风格定义URLURL将会更加简洁、更加规范、更加优雅。 注意事项 REST是风格是约定方式约定不是规定可以打破描述模块的功能通常使用复数也就是加s的格式来描述表示此类资源而非单个资源。如users、emps、books… 2、开发规范-统一响应结果
前后端工程在进行交互时使用统一响应结果 Result。
package com.itheima.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;Data
NoArgsConstructor
AllArgsConstructor
public class Result {private Integer code;//响应码1 代表成功; 0 代表失败private String msg; //响应信息 描述字符串private Object data; //返回的数据//增删改 成功响应public static Result success(){return new Result(1,success,null);}//查询 成功响应public static Result success(Object data){return new Result(1,success,data);}//失败响应public static Result error(String msg){return new Result(0,msg,null);}
}3、开发流程
我们在进行功能开发时都是根据如下流程进行 查看页面原型明确需求 根据页面原型和需求进行表结构设计、编写接口文档(已提供) 阅读接口文档 思路分析 功能接口开发 就是开发后台的业务功能一个业务功能我们称为一个接口 功能接口测试 功能开发完毕后先通过Postman进行功能接口测试测试通过后再和前端进行联调测试 前后端联调测试 和前端开发人员开发好的前端工程一起测试
2. 部门管理
我们按照前面学习的开发流程开始完成功能开发。首先按照之前分析的需求完成部门管理的功能开发。
开发的部门管理功能包含
查询部门删除部门新增部门更新部门不讲解自己独立完成
2.1 查询部门
2.1.1 原型和需求 查询的部门的信息部门ID、部门名称、修改时间 通过页面原型以及需求描述我们可以看到部门查询是不需要考虑分页操作的。 2.1.2 接口文档
部门列表查询 基本信息 请求路径/depts请求方式GET接口描述该接口用于部门列表数据查询请求参数 无 响应数据 参数格式application/json 参数说明 参数名类型是否必须备注codenumber必须响应码1 代表成功0 代表失败msgstring非必须提示信息dataobject[ ]非必须返回的数据|- idnumber非必须id|- namestring非必须部门名称|- createTimestring非必须创建时间|- updateTimestring非必须修改时间响应数据样例 {code: 1,msg: success,data: [{id: 1,name: 学工部,createTime: 2022-09-01T23:06:29,updateTime: 2022-09-01T23:06:29},{id: 2,name: 教研部,createTime: 2022-09-01T23:06:29,updateTime: 2022-09-01T23:06:29}]
}2.1.3 思路分析 2.1.4 功能开发
通过查看接口文档部门列表查询 请求路径/depts 请求方式GET 请求参数无 响应数据json格式 DeptController
Slf4j
RestController
public class DeptController {Autowiredprivate DeptService deptService;//RequestMapping(value /depts , method RequestMethod.GET)GetMapping(/depts)public Result list(){log.info(查询所有部门数据);ListDept deptList deptService.list();return Result.success(deptList);}
}Slf4j注解源码 DeptService业务接口
public interface DeptService {/*** 查询所有的部门数据* return 存储Dept对象的集合*/ListDept list();
}DeptServiceImpl业务实现类
Slf4j
Service
public class DeptServiceImpl implements DeptService {Autowiredprivate DeptMapper deptMapper;Overridepublic ListDept list() {ListDept deptList deptMapper.list();return deptList;}
} DeptMapper
Mapper
public interface DeptMapper {//查询所有部门数据Select(select id, name, create_time, update_time from dept)ListDept list();
}2.1.5 功能测试
功能开发完成后我们就可以启动项目然后打开postman发起GET请求访问 http://localhost:8080/depts 2.2 前后端联调
完成了查询部门的功能我们也通过postman工具测试通过了下面我们再基于前后端分离的方式进行接口联调。具体操作如下
1、将资料中提供的前端环境文件夹中的压缩包拷贝到一个没有中文不带空格的目录下 2、拷贝到一个没有中文不带空格的目录后进行解压解压到当前目录 3、启动nginx 4、打开浏览器访问http://localhost:90 5、测试部门管理 - 查询部门列表 说明只要按照接口文档开发功能接口就能保证前后端程序交互 后端严格遵守接口文档进行功能接口开发前端严格遵守接口文档访问功能接口 2.3 删除部门
查询部门的功能我们搞定了下面我们开始完成删除部门的功能开发。
2.3.1 需求 点击部门列表后面操作栏的 “删除” 按钮就可以删除该部门信息。 此时前端只需要给服务端传递一个ID参数就可以了。 我们从接口文档中也可以看得出来。
2.3.2 接口文档
删除部门 基本信息 请求路径/depts/{id}请求方式DELETE接口描述该接口用于根据ID删除部门数据请求参数 参数格式路径参数 参数说明 参数名类型是否必须备注idnumber必须部门ID请求参数样例 /depts/1响应数据 参数格式application/json 参数说明 参数名类型是否必须备注codenumber必须响应码1 代表成功0 代表失败msgstring非必须提示信息dataobject非必须返回的数据响应数据样例 {code:1,msg:success,data:null
}2.3.3 思路分析 接口文档规定 前端请求路径/depts/{id}前端请求方式DELETE 问题1怎么在controller中接收请求路径中的路径参数 PathVariable问题2如何限定请求方式是delete DeleteMapping2.3.4 功能开发
通过查看接口文档删除部门 请求路径/depts/{id} 请求方式DELETE 请求参数路径参数 {id} 响应数据json格式 DeptController
Slf4j
RestController
public class DeptController {Autowiredprivate DeptService deptService;DeleteMapping(/depts/{id})public Result delete(PathVariable Integer id) {//日志记录log.info(根据id删除部门);//调用service层功能deptService.delete(id);//响应return Result.success();}//省略...
}DeptService
public interface DeptService {/*** 根据id删除部门* param id 部门id*/void delete(Integer id);//省略...
}DeptServiceImpl
Slf4j
Service
public class DeptServiceImpl implements DeptService {Autowiredprivate DeptMapper deptMapper;Overridepublic void delete(Integer id) {//调用持久层删除功能deptMapper.deleteById(id);}//省略...
}DeptMapper
Mapper
public interface DeptMapper {/*** 根据id删除部门信息* param id 部门id*/Delete(delete from dept where id #{id})void deleteById(Integer id);//省略...
}2.3.5 功能测试
删除功能开发完成后重新启动项目使用postman发起DELETE请求 2.3.6 前后端联调
打开浏览器测试后端功能接口 2.4 新增部门
我们前面已完成了查询部门、删除部门两个功能也熟悉了开发的流程。下面我们继续完成新增部门功能。
2.4.1 需求 点击 “新增部门” 按钮弹出新增部门对话框输入部门名称点击 “保存” 将部门信息保存到数据库。
2.4.2 接口文档
添加部门 基本信息 请求路径/depts请求方式POST接口描述该接口用于添加部门数据请求参数 格式application/json 参数说明 参数名类型是否必须备注namestring必须部门名称请求参数样例 {name: 教研部
}响应数据 参数格式application/json 参数说明 参数名类型是否必须备注codenumber必须响应码1 代表成功0 代表失败msgstring非必须提示信息dataobject非必须返回的数据响应数据样例 {code:1,msg:success,data:null
}2.4.3 思路分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rWAHAjIB-1681663580365)(assets/image-20221214115519648.png)] 接口文档规定 前端请求路径/depts前端请求方式POST前端请求参数 (Json格式){ “name”: “教研部” } 问题1如何限定请求方式是POST PostMapping问题2怎么在controller中接收json格式的请求参数 RequestBody //把前端传递的json数据填充到实体类中2.4.4 功能开发
通过查看接口文档新增部门 请求路径/depts 请求方式POST 请求参数json格式 响应数据json格式 DeptController
Slf4j
RestController
public class DeptController {Autowiredprivate DeptService deptService;PostMapping(/depts)public Result add(RequestBody Dept dept){//记录日志log.info(新增部门{},dept);//调用service层添加功能deptService.add(dept);//响应return Result.success();}//省略...
}DeptService
public interface DeptService {/*** 新增部门* param dept 部门对象*/void add(Dept dept);//省略...
}
DeptServiceImpl
Slf4j
Service
public class DeptServiceImpl implements DeptService {Autowiredprivate DeptMapper deptMapper;Overridepublic void add(Dept dept) {//补全部门数据dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());//调用持久层增加功能deptMapper.inser(dept);}//省略...
}
DeptMapper
Mapper
public interface DeptMapper {Insert(insert into dept (name, create_time, update_time) values (#{name},#{createTime},#{updateTime}))void inser(Dept dept);//省略...
}2.4.5 功能测试
新增功能开发完成后重新启动项目使用postman发起POST请求 2.4.6 前后端联调
打开浏览器测试后端功能接口 2.4.7 请求路径
我们部门管理的查询、删除、新增功能全部完成了接下来我们要对controller层的代码进行优化。
首先我们先来看下目前controller层代码 以上三个方法上的请求路径存在一个共同点都是以/depts作为开头。重复了 在Spring当中为了简化请求路径的定义可以把公共的请求路径直接抽取到类上在类上加一个注解RequestMapping并指定请求路径/depts。代码参照如下 优化前后的对比 注意事项一个完整的请求路径应该是类上RequestMapping的value属性 方法上的 RequestMapping的value属性 3. 员工管理
完成了部门管理的功能开发之后我们进入到下一环节员工管理功能的开发。 基于以上原型我们可以把员工管理功能分为
分页查询今天完成带条件的分页查询今天完成删除员工今天完成新增员工后续完成修改员工后续完成
那下面我们就先从分页查询功能开始学习。
3.1 分页查询
3.1.1 基础分页
3.1.1.1 需求分析
我们之前做的查询功能是将数据库中所有的数据查询出来并展示到页面上试想如果数据库中的数据有很多(假设有十几万条)的时候将数据全部展示出来肯定不现实那如何解决这个问题呢 使用分页解决这个问题。每次只展示一页的数据比如一页展示10条数据如果还想看其他的数据可以通过点击页码进行查询。 要想从数据库中进行分页查询我们要使用LIMIT关键字格式为limit 开始索引 每页显示的条数 查询第1页数据的SQL语句是 select * from emp limit 0,10;查询第2页数据的SQL语句是 select * from emp limit 10,10;查询第3页的数据的SQL语句是 select * from emp limit 20,10;观察以上SQL语句发现 开始索引一直在改变 每页显示条数是固定的 开始索引的计算公式 开始索引 (当前页码 - 1) * 每页显示条数 我们继续基于页面原型继续分析得出以下结论
前端在请求服务端时传递的参数 当前页码 page每页显示条数 pageSize 后端需要响应什么数据给前端 所查询到的数据列表存储到List 集合中总记录数 后台给前端返回的数据包含List集合(数据列表)、total(总记录数) 而这两部分我们通常封装到PageBean对象中并将该对象转换为json格式的数据响应回给浏览器。 Data
NoArgsConstructor
AllArgsConstructor
public class PageBean {private Long total; //总记录数private List rows; //当前页数据列表
}3.1.1.2 接口文档
员工列表查询 基本信息 请求路径/emps请求方式GET接口描述该接口用于员工列表数据的条件分页查询请求参数 参数格式queryString 参数说明 参数名称是否必须示例备注name否张姓名gender否1性别 , 1 男 , 2 女begin否2010-01-01范围匹配的开始时间(入职日期)end否2020-01-01范围匹配的结束时间(入职日期)page是1分页查询的页码如果未指定默认为1pageSize是10分页查询的每页记录数如果未指定默认为10请求数据样例 /emps?name张gender1begin2007-09-01end2022-09-01page1pageSize10响应数据 参数格式application/json 参数说明 名称类型是否必须默认值备注其他信息codenumber必须响应码, 1 成功 , 0 失败msgstring非必须提示信息dataobject必须返回的数据|- totalnumber必须总记录数|- rowsobject []必须数据列表item 类型: object|- idnumber非必须id|- usernamestring非必须用户名|- namestring非必须姓名|- passwordstring非必须密码|- entrydatestring非必须入职日期|- gendernumber非必须性别 , 1 男 ; 2 女|- imagestring非必须图像|- jobnumber非必须职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师|- deptIdnumber非必须部门id|- createTimestring非必须创建时间|- updateTimestring非必须更新时间响应数据样例 {code: 1,msg: success,data: {total: 2,rows: [{id: 1,username: jinyong,password: 123456,name: 金庸,gender: 1,image: https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-02-00-27-53B.jpg,job: 2,entrydate: 2015-01-01,deptId: 2,createTime: 2022-09-01T23:06:30,updateTime: 2022-09-02T00:29:04},{id: 2,username: zhangwuji,password: 123456,name: 张无忌,gender: 1,image: https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-02-00-27-53B.jpg,job: 2,entrydate: 2015-01-01,deptId: 2,createTime: 2022-09-01T23:06:30,updateTime: 2022-09-02T00:29:04}]}
}3.1.1.3 思路分析 分页查询需要的数据封装在PageBean对象中 3.1.1.4 功能开发
通过查看接口文档员工列表查询 请求路径/emps 请求方式GET 请求参数跟随在请求路径后的参数字符串。 例/emps?page1pageSize10 响应数据json格式 EmpController
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 {Autowiredprivate EmpService empService;//条件分页查询GetMappingpublic 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);}
}RequestParam(defaultValue“默认值”) //设置请求参数默认值 EmpService
public interface EmpService {/*** 条件分页查询* param page 页码* param pageSize 每页展示记录数* return*/PageBean page(Integer page, Integer pageSize);
}EmpServiceImpl
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 {Autowiredprivate EmpMapper empMapper;Overridepublic PageBean page(Integer page, Integer pageSize) {//1、获取总记录数Long count empMapper.count();//2、获取分页查询结果列表Integer start (page - 1) * pageSize; //计算起始索引 , 公式: (页码-1)*页大小ListEmp empList empMapper.list(start, pageSize);//3、封装PageBean对象PageBean pageBean new PageBean(count , empList);return pageBean;}
}EmpMapper
Mapper
public interface EmpMapper {//获取总记录数Select(select count(*) from emp)public Long count();//获取当前页的结果列表Select(select * from emp limit #{start}, #{pageSize})public ListEmp list(Integer start, Integer pageSize);
}3.1.1.5 功能测试
功能开发完成后重新启动项目使用postman发起POST请求 3.1.1.6 前后端联调
打开浏览器测试后端功能接口 3.1.2 分页插件
3.1.2.1 介绍
前面我们已经完了基础的分页查询大家会发现分页查询功能编写起来比较繁琐。 在Mapper接口中定义两个方法执行两条不同的SQL语句 查询总记录数指定页码的数据列表 在Service当中调用Mapper接口的两个方法分别获取总记录数、查询结果列表然后在将获取的数据结果封装到PageBean对象中。 大家思考下在未来开发其他项目只要涉及到分页查询功能(例订单、用户、支付、商品)都必须按照以上操作完成功能开发 结论原始方式的分页查询存在着步骤固定、代码频繁的问题
解决方案可以使用一些现成的分页插件完成。对于Mybatis来讲现在最主流的就是PageHelper。 PageHelper是Mybatis的一款功能强大、方便易用的分页插件支持任何形式的单标、多表的分页查询。 官网https://pagehelper.github.io/ 在执行empMapper.list()方法时就是执行select * from emp 语句怎么能够实现分页操作呢 分页插件帮我们完成了以下操作 先获取到要执行的SQL语句select * from emp把SQL语句中的字段列表变为count(*)执行SQL语句select count(*) from emp //获取到总记录数再对要执行的SQL语句select * from emp 进行改造在末尾添加 limit ? , ?执行改造后的SQL语句select * from emp limit ? , ? 3.1.2.2 代码实现
当使用了PageHelper分页插件进行分页就无需再Mapper中进行手动分页了。 在Mapper中我们只需要进行正常的列表查询即可。在Service层中调用Mapper的方法之前设置分页参数在调用Mapper方法执行查询之后解析分页结果并将结果封装到PageBean对象中返回。
1、在pom.xml引入依赖
dependencygroupIdcom.github.pagehelper/groupIdartifactIdpagehelper-spring-boot-starter/artifactIdversion1.4.2/version
/dependency2、EmpMapper
Mapper
public interface EmpMapper {//获取当前页的结果列表Select(select * from emp)public ListEmp page(Integer start, Integer pageSize);
}3、EmpServiceImpl
Override
public PageBean page(Integer page, Integer pageSize) {// 设置分页参数PageHelper.startPage(page, pageSize); // 执行分页查询ListEmp empList empMapper.list(name,gender,begin,end); // 获取分页结果PageEmp p (PageEmp) empList; //封装PageBeanPageBean pageBean new PageBean(p.getTotal(), p.getResult()); return pageBean;
}3.1.2.3 测试
功能开发完成后我们重启项目工程打开postman发起GET请求访问 http://localhost:8080/emps?page1pageSize5 后端程序SQL输出 3.2 分页查询(带条件)
完了分页查询后下面我们需要在分页查询的基础上添加条件。
3.2.1 需求 通过员工管理的页面原型我们可以看到员工列表页面的查询不仅仅需要考虑分页还需要考虑查询条件。 分页查询我们已经实现了接下来我们需要考虑在分页查询的基础上再加上查询条件。
我们看到页面原型及需求中描述搜索栏的搜索条件有三个分别是
姓名模糊匹配性别精确匹配入职日期范围匹配
select *
from emp
where name like concat(%,张,%) -- 条件1根据姓名模糊匹配and gender 1 -- 条件2根据性别精确匹配and entrydate between 2000-01-01 and 2010-01-01 -- 条件3根据入职日期范围匹配
order by update_time desc;而且上述的三个条件都是可以传递也可以不传递的也就是动态的。 我们需要使用前面学习的Mybatis中的动态SQL 。
3.2.2 思路分析 3.2.3 功能开发
通过查看接口文档员工列表查询 请求路径/emps 请求方式GET 请求参数 参数名称是否必须示例备注name否张姓名gender否1性别 , 1 男 , 2 女begin否2010-01-01范围匹配的开始时间(入职日期)end否2020-01-01范围匹配的结束时间(入职日期)page是1分页查询的页码如果未指定默认为1pageSize是10分页查询的每页记录数如果未指定默认为10 在原有分页查询的代码基础上进行改造
EmpController
Slf4j
RestController
RequestMapping(/emps)
public class EmpController {Autowiredprivate EmpService empService;//条件分页查询GetMappingpublic 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
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
Slf4j
Service
public class EmpServiceImpl implements EmpService {Autowiredprivate EmpMapper empMapper;Overridepublic PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {//设置分页参数PageHelper.startPage(page, pageSize);//执行条件分页查询ListEmp empList empMapper.list(name, gender, begin, end);//获取查询结果PageEmp p (PageEmp) empList;//封装PageBeanPageBean pageBean new PageBean(p.getTotal(), p.getResult());return pageBean;}
}EmpMapper
Mapper
public interface EmpMapper {//获取当前页的结果列表public ListEmp list(String name, Short gender, LocalDate begin, LocalDate end);
}EmpMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.itheima.mapper.EmpMapper!-- 条件分页查询 --select idlist resultTypecom.itheima.pojo.Empselect * from empwhereif testname ! null and name ! name like concat(%,#{name},%)/ifif testgender ! nulland gender #{gender}/ifif testbegin ! null and end ! nulland entrydate between #{begin} and #{end}/if/whereorder by update_time desc/select
/mapper3.2.4 功能测试
功能开发完成后重启项目工程打开postman发起GET请求 控制台SQL语句 3.2.5 前后端联调
打开浏览器测试后端功能接口 3.3 删除员工
查询员完成之后我们继续开发新的功能删除员工。
3.3.1 需求 当我们勾选列表前面的复选框然后点击 “批量删除” 按钮就可以将这一批次的员工信息删除掉了。也可以只勾选一个复选框仅删除一个员工信息。
问题我们需要开发两个功能接口吗一个删除单个员工一个删除多个员工
答案不需要。 只需要开发一个功能接口即可删除多个员工包含只删除一个员工
3.3.2 接口文档
删除员工 基本信息 请求路径/emps/{ids}请求方式DELETE接口描述该接口用于批量删除员工的数据信息请求参数 参数格式路径参数 参数说明 参数名类型示例是否必须备注ids数组 array1,2,3必须员工的id数组请求参数样例 /emps/1,2,3响应数据 参数格式application/json 参数说明 参数名类型是否必须备注codenumber必须响应码1 代表成功0 代表失败msgstring非必须提示信息dataobject非必须返回的数据响应数据样例 {code:1,msg:success,data:null
}3.3.3 思路分析 接口文档规定 前端请求路径/emps/{ids}前端请求方式DELETE 问题1怎么在controller中接收请求路径中的路径参数 PathVariable问题2如何限定请求方式是delete DeleteMapping问题3在Mapper接口中执行delete操作的SQL语句时条件中的id值是不确定的是动态的怎么实现呢 Mybatis中的动态SQLforeach3.3.4 功能开发
通过查看接口文档删除员工 请求路径/emps/{ids} 请求方式DELETE 请求参数路径参数 {ids} 响应数据json格式 EmpController
Slf4j
RestController
RequestMapping(/emps)
public class EmpController {Autowiredprivate EmpService empService;//批量删除DeleteMapping(/{ids})public Result delete(PathVariable ListInteger ids){empService.delete(ids);return Result.success();}//条件分页查询GetMappingpublic 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
public interface EmpService {/*** 批量删除操作* param ids id集合*/void delete(ListInteger ids);//省略...
}EmpServiceImpl
Slf4j
Service
public class EmpServiceImpl implements EmpService {Autowiredprivate EmpMapper empMapper;Overridepublic void delete(ListInteger ids) {empMapper.delete(ids);}//省略...
}EmpMapper
Mapper
public interface EmpMapper {//批量删除void delete(ListInteger ids);//省略...
}EmpMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.itheima.mapper.EmpMapper!--批量删除员工--select iddeletedelete from emp where id inforeach collectionids itemid open( close) separator,#{id}/foreach/select!-- 省略... --/mapper3.3.5 功能测试
功能开发完成后重启项目工程打开postman发起DELETE请求 控制台SQL语句 3.3.6 前后端联调
打开浏览器测试后端功能接口