文章目录
- 前言
- 一、需求
- 二、定义接口 BookAdminController
- 三、核心实现 BookBorrowService
- 新建 BookBorrowService 接口定义如下:
- 新建 BookBorrowServiceImpl 类,核心实现逻辑:
- 新建 BookBorrowBO
- 四、图书借阅状态枚举 BookBorrowStatusEnum
- 五、Postman测试
- 最后
前言
本文主要实战 管理员借阅审核分页列表,更多的是复习之前讲过的技术点,像API接口的定义、分页pageHelper的使用、角色权限的校验
等等,另外针对【图书借阅审核状态】引入了枚举
的使用。
按照规划,本专栏剩余的文章还会有很多新技术点,当然像本文这样的复习也少不了,唯有不断复习、不断强化,这样你才能一回生二回熟,将前面所学技术不断的在不同的场景下活学活用,举一反三,触类旁通,最后才会越用越熟练,熟成生巧,当有新需求时,当然就能更快的找到更优的落地方案!
因为我们需要实现的API还有一大把,所以对于接下来的文章,我的计划是穿插着综合实战,新技术点讲解,好戏还在后头,加油!
一、需求
当学生发起【图书借阅】的申请后,在管理员端提供【借阅审核列表】给管理员查看:谁要借阅哪本书,哪些是待审核的,哪些是审核通过的,哪些是驳回的请求,分页展示。
提前说明:学生的图书借阅接口还没有开发,我们是先从管理员端入手!
二、定义接口 BookAdminController
对于借阅审核列表,支持
管理员角色校验@Role
、分页参数
、状态status的筛选
,另外我们新注入了BookBorrowService
,代码如下:
@Autowired
private BookBorrowService bookBorrowService;
@Role
@GetMapping("/book/borrow/examine/list")
public TgResult<BookBorrowBO> getBookBorrowExamineList(@RequestParam("pageNum") Integer pageNum
, @RequestParam("pageSize") Integer pageSize, @RequestParam("status") Integer status) {
return TgResult.ok(bookBorrowService.getBookBorrowExamineList(pageNum, pageSize, status));
}
详细的角色权限校验@Role,请参考 7.5 拦截器实现 和 7.6 AOP实现
三、核心实现 BookBorrowService
新建 BookBorrowService 接口定义如下:
public interface BookBorrowService {
Page<BookBorrowBO> getBookBorrowExamineList(int pageNum, int pageSize, Integer status);
}
新建 BookBorrowServiceImpl 类,核心实现逻辑:
- 分页查询借阅表book_borrowing,支持按status筛选
- 通过studentId 查询学生信息
- 通过bookId 查询书名
- 通过verifyUserId 查询审核人
- 通过status 查询状态描述
我在【7.4】说明过,这里再重复说明一下:这里分开查询,主要考虑的是 用户、图书、学生等信息不经常修改,二期可以使用
Redis缓存优化
,如果用Join查询,回头再优化的话,改动的就会更多!
@Service
public class BookBorrowServiceImpl implements BookBorrowService {
@Autowired
private BookBorrowingMapper bookBorrowingMapper;
@Autowired
private BookMapper bookMapper;
@Autowired
private StudentMapper studentMapper;
@Autowired
private UserMapper userMapper;
@Override
public Page<BookBorrowBO> getBookBorrowExamineList(int pageNum, int pageSize, Integer status) {
// 图书借阅审核列表
BookBorrowingExample example = new BookBorrowingExample();
if (status != null) {
example.createCriteria().andStatusEqualTo(status);
}
// 查询并分页
Page<BookBorrowing> page = PageHelper.startPage(pageNum, pageSize)
.doSelectPage(() -> bookBorrowingMapper.selectByExample(example));
Page<BookBorrowBO> pageBO = new Page<>();
BeanUtils.copyProperties(page, pageBO);
for (BookBorrowing bookBorrowing : page.getResult()) {
BookBorrowBO bookBorrowBO = new BookBorrowBO();
BeanUtils.copyProperties(bookBorrowing, bookBorrowBO);
Student student = studentMapper.selectByPrimaryKey(bookBorrowBO.getStudentId());
// 借阅的学生
StudentBO studentBO = new StudentBO();
BeanUtils.copyProperties(student, studentBO);
bookBorrowBO.setStudent(studentBO);
// 书名
Book book = bookMapper.selectByPrimaryKey(bookBorrowBO.getBookId());
bookBorrowBO.setBookName(book.getBookName());
// 审核人
if (bookBorrowBO.getVerifyUserId() != null) {
User verifyUser = userMapper.selectByPrimaryKey(bookBorrowBO.getVerifyUserId());
bookBorrowBO.setVerifyUserName(verifyUser.getUserName());
}
// 状态描述
bookBorrowBO.setStatusDesc(BookBorrowStatusEnum.getMsgByCode(bookBorrowBO.getStatus()));
pageBO.add(bookBorrowBO);
}
return pageBO;
}
}
- 对于 BookBorrowStatusEnum.getMsgByCode,我在文章下节有说明!
- 其它的Mybatis的根据Mapper查询,使用的都是MBG生成的selectByPrimaryKey,即根据主键查询一条记录。如果生疏了,详见 5.6 Mybatis代码生成器Mybatis Generator (MBG)实战详解
新建 BookBorrowBO
@Data
public class BookBorrowBO implements Serializable {
private Integer id;
private Integer studentId;
private Integer bookId;
private Date borrowTime;
private Integer status;
private String rejectReason;
private Date verifyTime;
private Integer verifyUserId;
private Date returnTime;
private Date gmtCreate;
private Date gmtModified;
// BookBorrowing以外的字段
private StudentBO student;
private String statusDesc;
private String bookName;
private String verifyUserName;
}
四、图书借阅状态枚举 BookBorrowStatusEnum
枚举定义在tg-book-common
的enums包中,如下图:
Java中定义枚举使用
enum
关键字,并且支持成员变量
、构造方法
等,适用于定义一些状态码和描述。
对于图书借阅状态,共分4种:
- 0-待审核
- 1-审核通过
- 2-驳回
- 3-已还
对于一码一描述,可以通过定义两个字段code 和 msg,使用构造方法传入,代码如下:
/**
* 图书借阅状态枚举
**/
public enum BookBorrowStatusEnum {
Integer code;
String msg;
BookBorrowStatusEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return this.code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
然后,我们可以在BookBorrowStatusEnum的最上方,中添加定义的4种状态:
/**
* 图书借阅状态枚举
**/
public enum BookBorrowStatusEnum {
TO_BE_EXAMINE(0, "待审核"),
APPROVED(1, "审核通过"),
REJECTED(2, "驳回"),
RETURNED(3, "已还"),
;
Integer code;
String msg;
BookBorrowStatusEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return this.code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
并且,可以像类一样,定义静态方法,例如在BookBorrowStatusEnum定义静态方法:根据code获取msg
/**
* 根据code获取msg
**/
public static String getMsgByCode(Integer code) {
for (BookBorrowStatusEnum e : BookBorrowStatusEnum.values()) {
if (e.getCode().equals(code)) {
return e.getMsg();
}
}
return null;
}
同理,我们再定义一个下文使用的图书状态枚举
:
/**
* 图书状态枚举
**/
public enum BookStatusEnum {
FREE(0, "空闲"),
BORROWING(1, "借阅中"),
;
Integer code;
String msg;
BookStatusEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return this.code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
五、Postman测试
先用SQL模拟一条学生借阅记录数据
INSERT INTO `db_book`.`book_borrowing`
(`student_id`, `book_id`, `borrow_time`, `status`, `reject_reason`
, `verify_time`, `verify_user_id`, `return_time`, `gmt_create`, `gmt_modified`)
VALUES (1, 2, '2023-04-08 03:10:00', 0, ''
, NULL, NULL, NULL, '2023-07-29 03:10:00', NULL);
再用Postman请求status=0的数据,结果如下:
最后
想要看更多实战好文章,还是给大家推荐我的实战专栏–>《基于SpringBoot+SpringCloud+Vue前后端分离项目实战》,由我和 前端狗哥 合力打造的一款专栏,可以让你从0到1快速拥有企业级规范的项目实战经验!
具体的优势、规划、技术选型都可以在《开篇》试读!
订阅专栏后可以添加我的微信,我会为每一位用户进行针对性指导!
另外,别忘了关注我:天罡gg ,发布新文不容易错过: https://blog.csdn.net/scm_2008