前言

前一篇文章 图书管理系统实战(上)中,我们已经编写了 pojo、dao 层以及配置 dao 层对应的 mapper,从现在开始,我们开始编写 service 层和 controller 层。

service 层

预约业务操作码

在正式编写 service 层之前,我们先定义一个预约图书操作返回码的数据字段,用于反馈给客户信息;

返回码 说明
1 预约成功
0 预约失败
-1 预约重复
-2 系统异常
  1. package com.cunyu.utils;
  2. import com.cunyu.dto.AppointDto;
  3. import lombok.AllArgsConstructor;
  4. import lombok.Getter;
  5. /**
  6. * @author : cunyu
  7. * @version : 1.0
  8. * @className : AppointStateEnum
  9. * @date : 2020/7/24 10:50
  10. * @description : 定义预约业务的数据字典
  11. */
  12. @Getter
  13. @AllArgsConstructor
  14. public enum AppointStateEnum {
  15. SUCCESS(1, "预约成功"), FAILURE(0, "预约失败"), REPEAT(-1, "预约重复"), SYSTEMERROR(-2, "系统异常");
  16. private int state;
  17. private String stateInfo;
  18. /**
  19. * @param stat 状态码
  20. * @return
  21. * @description 获取状态码对应 enum
  22. * @date 2020/7/24 10:57
  23. * @author cunyu1943
  24. * @version 1.0
  25. */
  26. public static AppointStateEnum stateOf(int stat) {
  27. for (AppointStateEnum state : values()
  28. ) {
  29. if (stat == state.getState()) {
  30. return state;
  31. }
  32. }
  33. return null;
  34. }
  35. }

数据传输层

定义好预约业务的数据字典之后,新建一个数据传输类用来传输我们的预约结果;

  1. package com.cunyu.dto;
  2. import com.cunyu.pojo.Appointment;
  3. import com.cunyu.utils.AppointStateEnum;
  4. import lombok.Data;
  5. import lombok.NoArgsConstructor;
  6. /**
  7. * @author : cunyu
  8. * @version : 1.0
  9. * @className : AppointDto
  10. * @date : 2020/7/24 10:46
  11. * @description : 用于数据传输,封装
  12. */
  13. @Data
  14. @NoArgsConstructor
  15. public class AppointDto {
  16. private int bookId;
  17. // 状态码
  18. private int state;
  19. // 状态信息
  20. private String stateInfo;
  21. // 预约成功的对象
  22. private Appointment appointment;
  23. // 预约失败的构造器
  24. public AppointDto(int bookId, AppointStateEnum appointStateEnum) {
  25. this.bookId = bookId;
  26. this.state = appointStateEnum.getState();
  27. this.stateInfo = appointStateEnum.getStateInfo();
  28. }
  29. // 预约成功的构造器
  30. public AppointDto(int bookId, AppointStateEnum appointStateEnum, Appointment appointment) {
  31. this.bookId = bookId;
  32. this.state = appointStateEnum.getState();
  33. this.stateInfo = appointStateEnum.getStateInfo();
  34. this.appointment = appointment;
  35. }
  36. }

service 业务代码编写

BookService.java

  1. package com.cunyu.service;
  2. import com.cunyu.dto.AppointDto;
  3. import com.cunyu.pojo.Book;
  4. import java.util.List;
  5. /**
  6. * @author : cunyu
  7. * @version : 1.0
  8. * @className : BookService
  9. * @date : 2020/7/24 10:44
  10. * @description : Book 业务接口
  11. */
  12. public interface BookService {
  13. /**
  14. * @param bookId 图书 ID
  15. * @return 对应 ID 的图书
  16. * @description 根据图书 id 查询图书
  17. * @date 2020/7/24 11:41
  18. * @author cunyu1943
  19. * @version 1.0
  20. */
  21. Book getById(int bookId);
  22. /**
  23. * @param
  24. * @return 所有图书的列表
  25. * @description 获取图书列表
  26. * @date 2020/7/24 11:41
  27. * @author cunyu1943
  28. * @version 1.0
  29. */
  30. List<Book> getList();
  31. /**
  32. * @param bookId 图书 id
  33. * @param studentId 学生 Id
  34. * @return
  35. * @description 返回预约结果
  36. * @date 2020/7/24 11:39
  37. * @author cunyu1943
  38. * @version 1.0
  39. */
  40. AppointDto appoint(int bookId, int studentId);
  41. }

BookServiceImpl.java

  1. package com.cunyu.service.impl;
  2. import com.cunyu.dao.AppointmentDao;
  3. import com.cunyu.dao.BookDao;
  4. import com.cunyu.dto.AppointDto;
  5. import com.cunyu.pojo.Appointment;
  6. import com.cunyu.pojo.Book;
  7. import com.cunyu.service.BookService;
  8. import com.cunyu.utils.AppointStateEnum;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Service;
  11. import java.util.List;
  12. /**
  13. * @author : cunyu
  14. * @version : 1.0
  15. * @className : BookServiceImpl
  16. * @date : 2020/7/24 11:43
  17. * @description : Book 业务接口实现类
  18. */
  19. @Service
  20. public class BookServiceImpl implements BookService {
  21. // 依赖注入
  22. @Autowired
  23. private BookDao bookDao;
  24. @Autowired
  25. private AppointmentDao appointmentDao;
  26. public Book getById(int bookId) {
  27. return bookDao.queryById(bookId);
  28. }
  29. public List<Book> getList() {
  30. return bookDao.queryAll(0, 3);
  31. }
  32. public AppointDto appoint(int bookId, int studentId) {
  33. AppointDto appointDto = null;
  34. try {
  35. // 减库存
  36. int update = bookDao.reduceNumber(bookId);
  37. if (update <= 0) {
  38. System.out.println(AppointStateEnum.FAILURE);
  39. } else {
  40. // 执行预约操作
  41. int insert = appointmentDao.insertAppointment(bookId, studentId);
  42. if (insert <= 0) {
  43. System.out.println(AppointStateEnum.REPEAT);
  44. } else {
  45. Appointment appointment = appointmentDao.queryByKeyWithBook(bookId, studentId);
  46. appointDto = new AppointDto(bookId, AppointStateEnum.SUCCESS, appointment);
  47. }
  48. }
  49. } catch (Exception e) {
  50. e.printStackTrace();
  51. }
  52. return appointDto;
  53. }
  54. }

测试

  1. package com.cunyu.service.impl;
  2. import com.cunyu.service.BookService;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.test.context.ContextConfiguration;
  7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  8. /**
  9. * @author : cunyu
  10. * @version : 1.0
  11. * @className : BookServiceImplTest
  12. * @date : 2020/7/24 11:53
  13. * @description : BookServiceImpl 测试类
  14. */
  15. @RunWith(SpringJUnit4ClassRunner.class)
  16. @ContextConfiguration("classpath:spring/spring-*.xml")
  17. public class BookServiceImplTest {
  18. @Autowired
  19. private BookService bookService;
  20. @Test
  21. public void testAppoint() {
  22. int bookId = 1;
  23. int studentId = 18301343;
  24. System.out.println(bookService.appoint(bookId, studentId));
  25. }
  26. }

下图是我们测试后数据库中的数据,说明此时我们的 service 层接口测试成功。

后端具体实现(下) - 图1

封装结果

既然我们的 service 层接口和实现类都编写好了,我们就需要将结果进行封装成 json 格式,方便我们传到 controller 交互使用。

  1. package com.cunyu.dto;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. /**
  5. * @author : cunyu
  6. * @version : 1.0
  7. * @className : ResultDto
  8. * @date : 2020/7/24 12:11
  9. * @description : 封装结果为 json
  10. */
  11. @Data
  12. @NoArgsConstructor
  13. public class ResultDto<T> {
  14. // 是否预约成功
  15. private boolean success;
  16. // 预约成功返回的数据
  17. private T data;
  18. // 错误信息
  19. private String error;
  20. // 预约成功的构造器
  21. public ResultDto(boolean success, T data) {
  22. this.success = success;
  23. this.data = data;
  24. }
  25. // 预约失败的构造器
  26. public ResultDto(boolean success, String error) {
  27. this.success = success;
  28. this.error = error;
  29. }
  30. }

controller 层

编写好 service 层之后,我们就剩下最后的 controller 层了;

  1. package com.cunyu.controller;
  2. import com.cunyu.dto.AppointDto;
  3. import com.cunyu.dto.ResultDto;
  4. import com.cunyu.pojo.Book;
  5. import com.cunyu.service.BookService;
  6. import com.cunyu.utils.AppointStateEnum;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Controller;
  9. import org.springframework.ui.Model;
  10. import org.springframework.web.bind.annotation.*;
  11. import java.util.List;
  12. /**
  13. * @author : cunyu
  14. * @version : 1.0
  15. * @className : BookController
  16. * @date : 2020/7/24 12:20
  17. * @description : Book controller 层
  18. */
  19. @Controller
  20. @RequestMapping("/book")
  21. public class BookController {
  22. @Autowired
  23. private BookService bookService;
  24. // url:ip:port:/book/list
  25. @GetMapping("/list")
  26. private String list(Model model) {
  27. List<Book> bookList = bookService.getList();
  28. model.addAttribute("bookList", bookList);
  29. return "list";
  30. }
  31. @GetMapping(value = "/{bookId}/detail")
  32. private String detail(@PathVariable("bookId") Integer bookId, Model model) {
  33. if (bookId == null) {
  34. return "redirect:/book/list";
  35. }
  36. Book book = bookService.getById(bookId);
  37. if (book == null) {
  38. return "forward:/book/list";
  39. }
  40. model.addAttribute("book", book);
  41. return "detail";
  42. }
  43. //ajax 传递 json 数据到前端
  44. @RequestMapping(value = "/{bookId}/appoint", method = RequestMethod.POST, produces = {"application/json; charset=utf-8"})
  45. @ResponseBody
  46. private ResultDto<AppointDto> appoint(@PathVariable("bookId") Integer bookId, @RequestParam("studentId") Integer studentId) {
  47. if (studentId == null || studentId.equals("")) {
  48. return new ResultDto<>(false, "学号不能为空");
  49. }
  50. AppointDto appointDto = null;
  51. try {
  52. appointDto = bookService.appoint(bookId, studentId);
  53. } catch (Exception e) {
  54. e.printStackTrace();
  55. }
  56. return new ResultDto<AppointDto>(true, appointDto);
  57. }
  58. }

前端

好了,我们的后台就开发完毕了,接下来就可以去编写前端页面了。然后启动 Tomcat,访问对应 url 即可。

list.jsp

  1. <%--
  2. Created by IntelliJ IDEA.
  3. User: cunyu
  4. Date: 2020/7/23
  5. Time: 9:47
  6. To change this template use File | Settings | File Templates.
  7. --%>
  8. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  9. <html>
  10. <head>
  11. <title>图书列表页</title>
  12. </head>
  13. <body>
  14. <h1>${bookList}</h1>
  15. </body>
  16. </html>

后端具体实现(下) - 图2

detail.jsp

  1. <%--
  2. Created by IntelliJ IDEA.
  3. User: cunyu
  4. Date: 2020/7/23
  5. Time: 10:02
  6. To change this template use File | Settings | File Templates.
  7. --%>
  8. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  9. <html>
  10. <head>
  11. <title>图书详情页</title>
  12. </head>
  13. <body>
  14. <h1>${book.name}</h1>
  15. <h2>${book.bookId}</h2>
  16. <h2>${book.number}</h2>
  17. </body>
  18. </html>

后端具体实现(下) - 图3

总结

到此,我们的后台所有服务都写好了,SSM 框架整合配置,与应用实例部分已经结束,前端部分就简单写了个数据展示页面。

感兴趣的小伙伴可以接着去实现前哦 ~