文章目录
- 前言
- 一、需求
- 二、Service层
- 2.1 图书详情 - 基本信息接口
- BookDetailBO
- BookService
- BookServiceImpl
- 2.2 图书详情 - 图书评论接口
- BookCommentBO
- StudentBO
- BookCommentService
- BookCommentServiceImpl
- 三、Web层
- BookAdminController
- 四、PostMan测试
- 最后
前言
在前面的API开发中,有一些朋友私信我对定义的VO、BO、PO对象存在疑问,不太明白各层定义的对象的好处!都是失血或贫血对象,对象的字段又很相近,传递时拷贝来拷贝去,感觉用起来更麻烦,这么做到底有什么好处呢?
你是否有什么类似的疑问?对于没有实际案例场景的同学,我认为这是很正常的想法。但实际的场景:Service层获取到PO对象后,会根据不同场景做不同的组装、计算等逻辑,所以BO就很必要了!你可以这么想:如果只是对数据库PO的直接映射,是不是Service层都显的鸡肋?所以往往在实际的项目里,Service层才是最厚的那层,才是与你打交道最多的地方,所以对于数据库的PO对象包装一层的BO就很重要,它可以做很多事,慢慢领会吧!这里举一个我见过的最典型的反面例子:用户接口返回了加密后的密码!天呐,这祭天不冤枉吧~~
本文,我会通过需求,完整写出我开发图书详情相关接口(管理员端)的思路,这才是真正的实战!
一、需求
B端管理员端和C端学生端,都有图书详情的模块,大同小异,管理员侧重书评管理
,而学生侧重对自己有效的信息。主要区别如下:
- B端管理员端:展示图书的
所有评论
,包括不同状态(0-待审核 1-通过 2-驳回)的评论 - C端学生端:展示图书
审核通过的评论
,以及我是否收藏
本文主要实现的是管理员端
二、Service层
因为图书详情展示的内容较多,所以是需要与前端同学一起来定义,通常有两种做法:
- 一个接口,包括详情里的所有信息
- 多个接口,每个接口包括部分信息
我这里会采用多个接口
的方式,因为对于评论来说,会涉及到分页,一个接口并没有那么好处理!
我拆成两个接口:
- 图书详情 - 基本信息接口
- 图书详情 - 图书评论接口
2.1 图书详情 - 基本信息接口
BookDetailBO
图书详情,包括图书的全部信息 + 创建人 + 修改人
,我这里直接把PO字段都都拿了过来,实际项目中,尽可能仅返回产品设计原型和PRD中需要的字段。
@Data
public class BookDetailBO implements Serializable {
private Integer id;
private String bookNo;
private String bookName;
private Integer bookType;
private String author;
private String description;
private String publisher;
private Date publishDate;
private String coverImage;
private Integer status;
private Integer borrowCount;
private Integer commentCount;
private Boolean isRecommend;
private Integer createUserId;
private Integer modifyUserId;
private Date gmtCreate;
private Date gmtModified;
// Book外的字段
private String createUserName;
private String modifyUserName;
}
BookService
新增一个获取图书详情的接口方法,像这种见名知义的方法,一般我推荐不写注释。
BookDetailBO getBookDetail(Integer id);
BookServiceImpl
对于实现代码,如果你是一路跟着学过来的同学,我相信你能看懂、会写、可优化下面的代码~
@Override
public BookDetailBO getBookDetail(Integer id) {
// 图书基本信息
Book book = bookMapper.selectByPrimaryKey(id);
if (book == null) {
return null;
}
BookDetailBO detailBO = new BookDetailBO();
BeanUtils.copyProperties(book, detailBO);
// 图书创建人
User createUser = userMapper.selectByPrimaryKey(book.getCreateUserId());
detailBO.setCreateUserName(createUser.getUserName());
if (book.getModifyUserId() != null) {
// 图书修改人
if (book.getCreateUserId().equals(book.getModifyUserId())) {
detailBO.setModifyUserName(createUser.getUserName());
} else {
User modifyUser = userMapper.selectByPrimaryKey(book.getModifyUserId());
detailBO.setModifyUserName(modifyUser.getUserName());
}
}
return detailBO;
}
当然,实现有很多方式:分开查询的方式、Join表查询的方式。
这里分开查询,主要考虑的是有缓存优化
的空间,如果是Join查询,那么就没什么优化的空间!
2.2 图书详情 - 图书评论接口
BookCommentBO
对于评论列表,因为管理员可以查看全部评论,所以包括图书评论的全部信息 + 学生信息 + 审核人
。
返回学生信息,也是方便前端进行更丰富的展示,这主要取决于产品设计,大部分通用字段就直接全部返回了。
@Data
public class BookCommentBO implements Serializable {
private Integer id;
private Integer studentId;
private Integer bookId;
private Integer score;
private String comment;
private Integer status;
private Date verifyTime;
private Integer verifyUserId;
private Date gmtCreate;
private Date gmtModified;
// BookComment以外的字段
private StudentBO student;
private String verifyUserName;
}
StudentBO
对于学生StudentBO,管理员可能会查看相关信息,同理~
@Data
public class StudentBO implements Serializable {
private Integer id;
private Integer userId;
private String studentNo;
private String studentName;
private String nickName;
private String department;
private String idCardImage;
private Boolean isApproved;
private Boolean isFrozen;
private Date gmtCreate;
private Date gmtModified;
}
BookCommentService
新增的图书评论接口
public interface BookCommentService {
Page<BookCommentBO> getBookCommentPage(int pageNum, int pageSize, int bookId);
}
BookCommentServiceImpl
用到了上一节的分页功能:7.3 SpringBoot整合MyBatis分页插件github.pageHelper:实现图书列表API
@Service
public class BookCommentServiceImpl implements BookCommentService {
@Autowired
private BookCommentMapper bookCommentMapper;
@Autowired
private StudentMapper studentMapper;
@Autowired
private UserMapper userMapper;
@Override
public Page<BookCommentBO> getBookCommentPage(int pageNum, int pageSize, int bookId) {
// 图书的评论列表
BookCommentExample example = new BookCommentExample();
example.createCriteria().andBookIdEqualTo(bookId);
// 查询并分页
Page<BookComment> page = PageHelper.startPage(pageNum, pageSize)
.doSelectPage(() -> bookCommentMapper.selectByExample(example));
Page<BookCommentBO> pageBO = new Page<>();
BeanUtils.copyProperties(page, pageBO);
for (BookComment bookComment : page.getResult()) {
BookCommentBO bookCommentBO = new BookCommentBO();
BeanUtils.copyProperties(bookComment, bookCommentBO);
Student student = studentMapper.selectByPrimaryKey(bookCommentBO.getStudentId());
// 评论的学生
StudentBO studentBO = new StudentBO();
BeanUtils.copyProperties(student, studentBO);
bookCommentBO.setStudent(studentBO);
// 审核人
if (bookCommentBO.getVerifyUserId() != null) {
User verifyUser = userMapper.selectByPrimaryKey(bookCommentBO.getVerifyUserId());
bookCommentBO.setVerifyUserName(verifyUser.getUserName());
}
pageBO.add(bookCommentBO);
}
return pageBO;
}
}
三、Web层
BookAdminController
@Autowired
private BookService bookService;
@Autowired
private BookCommentService bookCommentService;
@GetMapping("/book/detail")
public TgResult<BookDetailBO> getBookDetail(@RequestParam("id") Integer id) {
return TgResult.ok(bookService.getBookDetail(id));
}
@GetMapping("/book/comment/list")
public TgResult<BookCommentBO> getBookCommentList(@RequestParam("pageNum") Integer pageNum
, @RequestParam("pageSize") Integer pageSize, @RequestParam("id") Integer id) {
return TgResult.ok(bookCommentService.getBookCommentPage(pageNum, pageSize, id));
}
都是之前讲过的代码,新注入了bookCommentService,并新增了两个接口。
四、PostMan测试
最后
想要看更多实战好文章,还是给大家推荐我的实战专栏–>《基于SpringBoot+SpringCloud+Vue前后端分离项目实战》,由我和 前端狗哥 合力打造的一款专栏,可以让你从0到1快速拥有企业级规范的项目实战经验!
具体的优势、规划、技术选型都可以在《开篇》试读!
订阅专栏后可以添加我的微信,我会为每一位用户进行针对性指导!
另外,别忘了关注我:天罡gg ,发布新文不容易错过: https://blog.csdn.net/scm_2008