图书管理系统(四)图书管理系统实战(2)
时间:2022-07-22
本文章向大家介绍图书管理系统(四)图书管理系统实战(2),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
目录
- 1. 前言
- 2. service 层
- 2.1 预约业务操作码
- 3.2 数据传输层
- 2.3 service 业务代码编写
- 2.4 测试
- 2.5 封装结果
- 3. controller 层
- 4. 前端
- 4.1 list.jsp
- 4.2 detail.jsp
- 5. 总结
1. 前言
前一篇文章 图书管理系统实战(一)[1] 中,我们已经编写了 pojo、dao 层以及配置 dao 层对应的 mapper,从现在开始,我们开始编写 service 层和 controller 层。
2. service 层
2.1 预约业务操作码
在正式编写 service 层之前,我们先定义一个预约图书操作返回码的数据字段,用于反馈给客户信息;
返回码 |
说明 |
---|---|
1 |
预约成功 |
0 |
预约失败 |
-1 |
预约重复 |
-2 |
系统异常 |
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;
}
}
3.2 数据传输层
定义好预约业务的数据字典之后,新建一个数据传输类用来传输我们的预约结果;
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;
}
}
2.3 service 业务代码编写
2.3.1 BookService.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);
}
2.3.2 BookServiceImpl.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;
}
}
2.4 测试
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 层接口测试成功。
2.5 封装结果
既然我们的 service 层接口和实现类都编写好了,我们就需要将结果进行封装成 json 格式,方便我们传到 controller 交互使用。
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<T> {
// 是否预约成功
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;
}
}
3. controller 层
编写好 service 层之后,我们就剩下最后的 controller 层了;
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);
}
}
4. 前端
好了,我们的后台就开发完毕了,接下来就可以去编写前端页面了。然后启动 Tomcat,访问对应 url 即可。
4.1 list.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" %>
<html>
<head>
<title>图书列表页</title>
</head>
<body>
<h1>${bookList}</h1>
</body>
</html>
4.2 detail.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" %>
<html>
<head>
<title>图书详情页</title>
</head>
<body>
<h1>${book.name}</h1>
<h2>${book.bookId}</h2>
<h2>${book.number}</h2>
</body>
</html>
5. 总结
到此,我们的后台所有服务都写好了,SSM 框架整合配置,与应用实例部分已经结束,前端部分就简单写了个数据展示页面。如果想要源码,我已经放到 Github[2],需要的可以去 Star 一波,哈哈!
参考资料
[1]Github: https://github.com/cunyu1943/book-manager
- 理解 Linux shell 中的一个方言:2>&1
- 大家知道什么是git中的 .gitignore吗?
- MySQL 8.0 新特性 :隐藏索引 Invisible Indexes
- 如何监控MySQL的复制延迟?
- Uber 的 Docker Mysql 应用
- Dubbo源码-从HelloWorld开始
- 【深度学习】用PaddlePaddle进行车牌识别(二)
- JavaScript 10分钟入门
- 外键约束
- OpenCV3.x中UMat介绍与使用
- OpenCV中KMeans算法介绍与应用
- LinkedIn 即时通信系统的优化
- javascript console输出图片?
- 快速搭建Storm集群环境
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 深入理解JavaScript闭包之闭包的使用场景
- Spring Boot 到底是个啥?
- Spring Boot 整合 Thymeleaf
- webapp打包为Android的apk包的一种方法
- Android应用之Hybird混合开发,集成web页面的方法尝试
- Spring Boot 通过 XML 的方式整合 MyBatis
- layUI登录界面验证码功能模块儿封装
- go语言微信公众号开发后台接口封装
- 【DB宝14】在Docker中只需2步即可拥有Oracle 11g企业版环境(11.2.0.4)
- 别忘了给gcc编译器工具链加上-fno-common选项
- 轻量安全的部署方案
- 算法集锦(34) | 强化学习| 出租车载客问题
- 前端测试题:(解析)关于ajax跨域的说法,下面错误的是?
- 什么才是定制化 IDE 的核心价值?
- RTOS内功修炼记(八)— CMSIS RTOS API,内核通用API接口