SSM 图书管理系统:后端具体实现(下)

语言: CN / TW / HK

theme: Chinese-red highlight: a11y-dark


小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

前言

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

service 层

预约业务操作码

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

| 返回码 | 说明 | | ------ | -------- | | 1 | 预约成功 | | 0 | 预约失败 | | -1 | 预约重复 | | -2 | 系统异常 |

```java package com.cunyu.utils;

import com.cunyu.dto.AppointDto; import lombok.AllArgsConstructor; import lombok.Getter;

/* * @author : cunyu * @version : 1.0 * @className : AppointStateEnum * @date : 2020/7/24 10:50 * @description : 定义预约业务的数据字典 /

@Getter @AllArgsConstructor public enum AppointStateEnum {

SUCCESS(1, "预约成功"), FAILURE(0, "预约失败"), REPEAT(-1, "预约重复"), SYSTEMERROR(-2, "系统异常");

private int state;
private String stateInfo;

/**
 * @param stat 状态码
 * @return
 * @description 获取状态码对应 enum
 * @date 2020/7/24 10:57
 * @author cunyu1943
 * @version 1.0
 */
public static AppointStateEnum stateOf(int stat) {
    for (AppointStateEnum state : values()
    ) {
        if (stat == state.getState()) {
            return state;
        }
    }
    return null;
}

} ```

数据传输层

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

```java package com.cunyu.dto;

import com.cunyu.pojo.Appointment; import com.cunyu.utils.AppointStateEnum; import lombok.Data; import lombok.NoArgsConstructor;

/* * @author : cunyu * @version : 1.0 * @className : AppointDto * @date : 2020/7/24 10:46 * @description : 用于数据传输,封装 /

@Data @NoArgsConstructor public class AppointDto { private int bookId; // 状态码 private int state; // 状态信息 private String stateInfo; // 预约成功的对象 private Appointment appointment;

//    预约失败的构造器
public AppointDto(int bookId, AppointStateEnum appointStateEnum) {
    this.bookId = bookId;
    this.state = appointStateEnum.getState();
    this.stateInfo = appointStateEnum.getStateInfo();
}

//    预约成功的构造器
public AppointDto(int bookId, AppointStateEnum appointStateEnum, Appointment appointment) {
    this.bookId = bookId;
    this.state = appointStateEnum.getState();
    this.stateInfo = appointStateEnum.getStateInfo();
    this.appointment = appointment;
}

} ```

service 业务代码编写

BookService.java

```java package com.cunyu.service;

import com.cunyu.dto.AppointDto; import com.cunyu.pojo.Book;

import java.util.List;

/* * @author : cunyu * @version : 1.0 * @className : BookService * @date : 2020/7/24 10:44 * @description : Book 业务接口 /

public interface BookService {

/**
 * @param bookId 图书 ID
 * @return 对应 ID 的图书
 * @description 根据图书 id 查询图书
 * @date 2020/7/24 11:41
 * @author cunyu1943
 * @version 1.0
 */
Book getById(int bookId);

/**
 * @param
 * @return 所有图书的列表
 * @description 获取图书列表
 * @date 2020/7/24 11:41
 * @author cunyu1943
 * @version 1.0
 */
List<Book> getList();

/**
 * @param bookId    图书 id
 * @param studentId 学生 Id
 * @return
 * @description 返回预约结果
 * @date 2020/7/24 11:39
 * @author cunyu1943
 * @version 1.0
 */
AppointDto appoint(int bookId, int studentId);

} ```

BookServiceImpl.java

```java package com.cunyu.service.impl;

import com.cunyu.dao.AppointmentDao; import com.cunyu.dao.BookDao; import com.cunyu.dto.AppointDto; import com.cunyu.pojo.Appointment; import com.cunyu.pojo.Book; import com.cunyu.service.BookService; import com.cunyu.utils.AppointStateEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;

import java.util.List;

/* * @author : cunyu * @version : 1.0 * @className : BookServiceImpl * @date : 2020/7/24 11:43 * @description : Book 业务接口实现类 /

@Service public class BookServiceImpl implements BookService { // 依赖注入 @Autowired private BookDao bookDao;

@Autowired
private AppointmentDao appointmentDao;

public Book getById(int bookId) {
    return bookDao.queryById(bookId);
}

public List<Book> getList() {
    return bookDao.queryAll(0, 3);
}

public AppointDto appoint(int bookId, int studentId) {
    AppointDto appointDto = null;
    try {
        // 减库存
        int update = bookDao.reduceNumber(bookId);
        if (update <= 0) {
            System.out.println(AppointStateEnum.FAILURE);
        } else {
            // 执行预约操作
            int insert = appointmentDao.insertAppointment(bookId, studentId);
            if (insert <= 0) {
                System.out.println(AppointStateEnum.REPEAT);
            } else {
                Appointment appointment = appointmentDao.queryByKeyWithBook(bookId, studentId);
                appointDto = new AppointDto(bookId, AppointStateEnum.SUCCESS, appointment);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return appointDto;
}

} ```

测试

```java package com.cunyu.service.impl;

import com.cunyu.service.BookService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/* * @author : cunyu * @version : 1.0 * @className : BookServiceImplTest * @date : 2020/7/24 11:53 * @description : BookServiceImpl 测试类 /

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring/spring-*.xml") public class BookServiceImplTest { @Autowired private BookService bookService;

@Test
public void testAppoint() {
    int bookId = 1;
    int studentId = 18301343;
    System.out.println(bookService.appoint(bookId, studentId));
}

} ```

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

封装结果

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

```java package com.cunyu.dto;

import lombok.Data; import lombok.NoArgsConstructor;

/* * @author : cunyu * @version : 1.0 * @className : ResultDto * @date : 2020/7/24 12:11 * @description : 封装结果为 json /

@Data @NoArgsConstructor public class ResultDto { // 是否预约成功 private boolean success; // 预约成功返回的数据 private T data; // 错误信息 private String error;

// 预约成功的构造器
public ResultDto(boolean success, T data) {
    this.success = success;
    this.data = data;
}

// 预约失败的构造器
public ResultDto(boolean success, String error) {
    this.success = success;
    this.error = error;
}

} ```

controller 层

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

```java package com.cunyu.controller;

import com.cunyu.dto.AppointDto; import com.cunyu.dto.ResultDto; import com.cunyu.pojo.Book; import com.cunyu.service.BookService; import com.cunyu.utils.AppointStateEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*;

import java.util.List;

/* * @author : cunyu * @version : 1.0 * @className : BookController * @date : 2020/7/24 12:20 * @description : Book controller 层 /

@Controller @RequestMapping("/book") public class BookController { @Autowired private BookService bookService;

// url:ip:port:/book/list
@GetMapping("/list")
private String list(Model model) {
    List<Book> bookList = bookService.getList();
    model.addAttribute("bookList", bookList);
    return "list";
}

@GetMapping(value = "/{bookId}/detail")
private String detail(@PathVariable("bookId") Integer bookId, Model model) {
    if (bookId == null) {
        return "redirect:/book/list";
    }

    Book book = bookService.getById(bookId);
    if (book == null) {
        return "forward:/book/list";
    }

    model.addAttribute("book", book);
    return "detail";
}

//ajax 传递 json 数据到前端
@RequestMapping(value = "/{bookId}/appoint", method = RequestMethod.POST, produces = {"application/json; charset=utf-8"})
@ResponseBody
private ResultDto<AppointDto> appoint(@PathVariable("bookId") Integer bookId, @RequestParam("studentId") Integer studentId) {
    if (studentId == null || studentId.equals("")) {
        return new ResultDto<>(false, "学号不能为空");
    }
    AppointDto appointDto = null;
    try {
        appointDto = bookService.appoint(bookId, studentId);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return new ResultDto<AppointDto>(true, appointDto);
}

} ```

前端

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

list.jsp

```jsp <%-- Created by IntelliJ IDEA. User: cunyu Date: 2020/7/23 Time: 9:47 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> 图书列表页

${bookList}

```

detail.jsp

```jsp <%-- Created by IntelliJ IDEA. User: cunyu Date: 2020/7/23 Time: 10:02 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> 图书详情页

${book.name}

${book.bookId}

${book.number}

```

总结

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

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