基于 Spring Boot实现的图书管理系统

Spring Boot图书管理系统详细分析文档

1. 项目概述

本文档对基于Spring Boot实现的图书管理系统进行详细分析。该项目是一个典型的Web应用程序,采用了Spring Boot框架,结合MyBatis作为ORM工具,实现了图书信息的管理功能,包括图书的添加、查询、修改和删除等操作,以及用户登录验证功能。

1.1 项目地址

项目Github地址

1.2 技术栈

  • 后端框架:Spring Boot
  • ORM框架:MyBatis
  • 数据库:MySQL
  • 前端技术:原生的框架

1.3 系统架构

该系统采用经典的Spring Boot MVC分层架构,主要包括以下几层:

  • 控制器层(Controller):处理HTTP请求,接收前端数据并返回响应
  • 服务层(Service):实现业务逻辑
  • 数据访问层(Mapper):通过MyBatis实现与数据库的交互
  • 数据模型层(Model):定义数据实体类
  • 数据库层(Database):存储系统数据

2. 项目结构分析

2.1 目录结构

项目采用标准的Maven项目结构,主要代码位于src/main/java/org/example/jd20250417springbookdemo目录下,按功能模块划分为多个包:

Mermaid 复制代码
src/main/java/org/example/jd20250417springbookdemo/
├── contant/          # 常量定义
├── controller/       # 控制器类
│   ├── BookInfoController.java
│   └── UserInfoController.java
├── enums/            # 枚举类
│   └── BookStatusEnum.java
├── mapper/           # MyBatis映射接口
│   ├── BookInfoMapper.java
│   └── UserInfoMapper.java
├── model/            # 数据模型类
│   ├── BookInfo.java
│   ├── PageRequest.java
│   ├── ResponseResult.java
│   ├── Result.java
│   └── UserInfo.java
├── service/          # 服务类
│   ├── BookInfoService.java
│   └── UserInfoService.java
└── Jd20250417SpringbookDemoApplication.java  # 应用程序入口类

2.2 数据流程

系统的数据流程如下图所示,展示了从Web浏览器发起请求到数据库操作的完整流程:

3. 核心组件详细分析

3.1 数据模型层(Model)

数据模型层定义了系统中使用的各种数据实体类,是系统的基础。

3.1.1 BookInfo.java

BookInfo类是图书信息的实体类,定义了图书的基本属性。

java 复制代码
public class BookInfo {
    private Integer bookId;      // 图书ID
    private String bookName;     // 图书名称
    private String author;       // 作者
    private Integer count;       // 数量
    private Double price;        // 价格
    private String publish;      // 出版社
    private Integer status;      // 状态(0-删除 1-正常 2-不可借阅)
    private String statusCN;     // 状态中文描述
    
    // getter和setter方法
    // ...
}

主要属性说明:

  • bookId:图书的唯一标识符
  • bookName:图书名称
  • author:图书作者
  • count:图书数量
  • price:图书价格
  • publish:出版社
  • status:图书状态,使用整数表示不同状态
  • statusCN:图书状态的中文描述
3.1.2 UserInfo.java

UserInfo类是用户信息的实体类,定义了用户的基本属性。

java 复制代码
public class UserInfo {
    private Integer userId;      // 用户ID
    private String userName;     // 用户名
    private String password;     // 密码
    
    // getter和setter方法
    // ...
}

主要属性说明:

  • userId:用户的唯一标识符
  • userName:用户名
  • password:用户密码
3.1.3 PageRequest.java

PageRequest类用于实现分页查询,定义了分页相关的属性。

java 复制代码
public class PageRequest {
    private Integer currentPage;  // 当前页码
    private Integer pageSize;     // 每页显示数量
    
    // getter和setter方法
    // ...
}

主要属性说明:

  • currentPage:当前页码
  • pageSize:每页显示的记录数量
3.1.4 ResponseResult.java 和 Result.java

这两个类用于统一处理API响应结果,提供了标准化的响应格式。

ResponseResult.java

java 复制代码
public class ResponseResult<T> {
    private Integer count;        // 总记录数
    private List<T> records;      // 数据记录列表
    private PageRequest pageRequest; // 分页请求信息
    
    // 构造方法和工具方法
    // ...
}

Result.java

java 复制代码
public class Result {
    private Boolean success;      // 是否成功
    private String code;          // 状态码
    private String message;       // 消息
    private Object data;          // 数据
    
    // 静态工厂方法
    public static Result success(Object data) {
        // 创建成功响应
    }
    
    public static Result fail(String message) {
        // 创建失败响应
    }
    
    // getter和setter方法
    // ...
}

3.2 数据访问层(Mapper)

数据访问层通过MyBatis框架实现与数据库的交互,定义了SQL操作接口。

3.2.1 BookInfoMapper.java

BookInfoMapper接口定义了对图书信息表的各种操作。

java 复制代码
@Mapper
public interface BookInfoMapper {
    // 添加图书
    @Insert("INSERT INTO `book_info`(`book_name`, `author`, `count`, `price`, `publish`, `status`) " +
            "VALUES (#{bookName}, #{author}, #{count}, #{price}, #{publish}, #{status})")
    void addBook(BookInfo bookInfo);
    
    // 分页查询图书
    @Select("<script>" +
            "SELECT * FROM `book_info` " +
            "WHERE `status` != 0 " +
            "LIMIT #{currentPage}, #{pageSize}" +
            "</script>")
    List<BookInfo> selectBooksByPage(PageRequest pageRequest);
    
    // 统计图书数量
    @Select("SELECT COUNT(*) FROM `book_info` WHERE `status` != 0")
    Integer count();
    
    // 根据ID查询图书
    @Select("SELECT * FROM `book_info` WHERE `book_id` = #{bookId}")
    BookInfo queryBookById(Integer bookId);
    
    // 更新图书信息
    @Update("<script>" +
            "UPDATE `book_info` " +
            "SET `book_name` = #{bookName}, " +
            "`author` = #{author}, " +
            "`count` = #{count}, " +
            "`price` = #{price}, " +
            "`publish` = #{publish}, " +
            "`status` = #{status} " +
            "WHERE `book_id` = #{bookId}" +
            "</script>")
    void updateBook(BookInfo bookInfo);
    
    // 批量删除图书(逻辑删除)
    @Update("<script>" +
            "UPDATE `book_info` SET `status` = 0 " +
            "WHERE `book_id` IN " +
            "<foreach collection='array' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    void batchDelete(Integer[] bookIds);
}

主要方法说明:

  • addBook:添加新图书
  • selectBooksByPage:分页查询图书列表
  • count:统计图书总数
  • queryBookById:根据ID查询图书详情
  • updateBook:更新图书信息
  • batchDelete:批量删除图书(逻辑删除,将状态设为0)
3.2.2 UserInfoMapper.java

UserInfoMapper接口定义了对用户信息表的操作。

java 复制代码
@Mapper
public interface UserInfoMapper {
    // 根据用户名查询用户信息
    @Select("SELECT * FROM `user_info` WHERE user_name = #{username}")
    UserInfo queryUserInfoByName(String username);
}

主要方法说明:

  • queryUserInfoByName:根据用户名查询用户信息,用于用户登录验证

3.3 服务层(Service)

服务层实现业务逻辑,调用数据访问层完成数据操作。

3.3.1 BookInfoService.java

BookInfoService类实现了图书管理的业务逻辑。

java 复制代码
@Service
public class BookInfoService {
    @Autowired
    private BookInfoMapper bookInfoMapper;
    
    // 添加图书
    public void addBook(BookInfo bookInfo) {
        bookInfoMapper.addBook(bookInfo);
    }
    
    // 分页查询图书列表
    public ResponseResult<BookInfo> getListByPage(PageRequest pageRequest) {
        // 1. 获取总记录数
        Integer count = bookInfoMapper.count();
        
        // 2. 获取当前页面的数据
        List<BookInfo> bookInfos = bookInfoMapper.selectBooksByPage(pageRequest);
        
        // 对结果进行二次处理 --> 处理状态码
        // 0-删除 1-正常 2-不可借阅
        for (BookInfo bookInfo : bookInfos) {
            // 前端展示时就能直接展示中文状态
            bookInfo.setStatusCN(BookStatusEnum.getStatusByCode(bookInfo.getStatus()).getDesc());
        }
        
        // 返回分页结果对象
        return new ResponseResult<>(count, bookInfos, pageRequest);
    }
    
    // 根据ID查询图书
    public BookInfo queryBookById(Integer bookId) {
        return bookInfoMapper.queryBookById(bookId);
    }
    
    // 更新图书信息
    public void updateBook(BookInfo bookInfo) {
        bookInfoMapper.updateBook(bookInfo);
    }
    
    // 批量删除图书
    public void batchDelete(Integer[] bookIds) {
        bookInfoMapper.batchDelete(bookIds);
    }
}

主要方法说明:

  • addBook:添加新图书
  • getListByPage:分页查询图书列表,并处理状态码转换为中文描述
  • queryBookById:根据ID查询图书详情
  • updateBook:更新图书信息
  • batchDelete:批量删除图书
3.3.2 UserInfoService.java

UserInfoService类实现了用户相关的业务逻辑。

java 复制代码
@Service
public class UserInfoService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    
    // 根据用户名查询用户信息
    public UserInfo queryUserNameByName(String username) {
        return userInfoMapper.queryUserInfoByName(username);
    }
}

主要方法说明:

  • queryUserNameByName:根据用户名查询用户信息,用于用户登录验证

3.4 控制器层(Controller)

控制器层处理HTTP请求,调用服务层完成业务操作。

3.4.1 BookInfoController.java

BookInfoController类处理图书相关的HTTP请求。

java 复制代码
@Slf4j
@RequestMapping("/book")
@RestController
public class BookInfoController {
    @Autowired
    private BookInfoService bookInfoService;
    
    // 添加图书
    @PostMapping(value = "/addBook", produces = "application/json")
    public Result addBook(@RequestBody BookInfo bookInfo) {
        log.info("添加图书,request: {}", bookInfo);
        
        // 参数校验
        if (!StringUtils.hasLength(bookInfo.getBookName()) ||
            !StringUtils.hasLength(bookInfo.getAuthor()) ||
            bookInfo.getCount() == null ||
            bookInfo.getPrice() == null ||
            !StringUtils.hasLength(bookInfo.getPublish()) ||
            bookInfo.getStatus() == null) {
            log.warn("添加图书,参数不合法, request: {}", bookInfo);
            
            // 检查各个参数并提供具体错误信息
            if (!StringUtils.hasLength(bookInfo.getBookName())) {
                return Result.fail("书名不能为空");
            }
            if (!StringUtils.hasLength(bookInfo.getAuthor())) {
                return Result.fail("作者不能为空");
            }
            if (bookInfo.getCount() == null) {
                return Result.fail("数量不能为空");
            }
            if (bookInfo.getPrice() == null) {
                return Result.fail("价格不能为空");
            }
            if (!StringUtils.hasLength(bookInfo.getPublish())) {
                return Result.fail("出版社不能为空");
            }
            if (bookInfo.getStatus() == null) {
                return Result.fail("状态不能为空");
            }
        }
        
        // 调用服务层添加图书
        bookInfoService.addBook(bookInfo);
        return Result.success(true);
    }
    
    // 分页查询图书列表
    @GetMapping("/list")
    public ResponseResult<BookInfo> getBookList(PageRequest pageRequest) {
        return bookInfoService.getListByPage(pageRequest);
    }
    
    // 根据ID查询图书
    @GetMapping("/query/{id}")
    public Result queryBook(@PathVariable("id") Integer id) {
        BookInfo bookInfo = bookInfoService.queryBookById(id);
        return Result.success(bookInfo);
    }
    
    // 更新图书信息
    @PutMapping("/update")
    public Result updateBook(@RequestBody BookInfo bookInfo) {
        // 参数校验
        if (bookInfo.getBookId() == null) {
            return Result.fail("图书ID不能为空");
        }
        
        // 调用服务层更新图书
        bookInfoService.updateBook(bookInfo);
        return Result.success(true);
    }
    
    // 批量删除图书
    @DeleteMapping("/delete")
    public Result deleteBooks(Integer[] ids) {
        if (ids == null || ids.length == 0) {
            return Result.fail("请选择要删除的图书");
        }
        
        // 调用服务层批量删除图书
        bookInfoService.batchDelete(ids);
        return Result.success(true);
    }
}

主要方法说明:

  • addBook:处理添加图书的POST请求,包含参数校验
  • getBookList:处理分页查询图书列表的GET请求
  • queryBook:处理根据ID查询图书的GET请求
  • updateBook:处理更新图书信息的PUT请求
  • deleteBooks:处理批量删除图书的DELETE请求
3.4.2 UserInfoController.java

UserInfoController类处理用户相关的HTTP请求。

java 复制代码
@Slf4j
@RequestMapping("/user")
@RestController
public class UserInfoController {
    @Autowired
    private UserInfoService userInfoService;
    
    // 用户登录
    @RequestMapping("/login")
    public Result login(String username, String password, HttpSession session) {
        // 验证步骤
        // 1. 参数是否规范
        // 2. 检验用户名和密码是否正确
        // 3. 设置session
        // 4. 返回结果
        
        log.info("username: " + username);
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return Result.fail("用户名或密码不能为空");
        }
        
        // 客户端输入的参数和数据库中的参数进行比较
        UserInfo userInfo = userInfoService.queryUserNameByName(username);
        
        // 1. 先确认用户是否存在 2. 再确认密码是否正确
        if (userInfo == null) {
            return Result.fail("用户名不存在");
        }
        
        if (password.equals(userInfo.getPassword())) {
            // 清空密码
            userInfo.setPassword("");
            session.setAttribute(Constants.SESSION_USER_KEY, userInfo);
            return Result.success(true);
        }
        
        return Result.fail("密码错误");
    }
}

主要方法说明:

  • login:处理用户登录请求,验证用户名和密码,成功后将用户信息存入Session

3.5 枚举类(Enums)

3.5.1 BookStatusEnum.java

BookStatusEnum枚举定义了图书的不同状态。

java 复制代码
public enum BookStatusEnum {
    DELETE(0, "删除"),
    NORMAL(1, "正常"),
    CANNOT_BORROW(2, "不可借阅");
    
    private final Integer code;
    private final String desc;
    
    BookStatusEnum(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    
    // 根据状态码获取对应的枚举值
    public static BookStatusEnum getStatusByCode(Integer code) {
        for (BookStatusEnum status : BookStatusEnum.values()) {
            if (status.getCode().equals(code)) {
                return status;
            }
        }
        return null;
    }
    
    // getter方法
    // ...
}

状态说明:

  • DELETE(0, "删除"):图书已删除
  • NORMAL(1, "正常"):图书状态正常,可借阅
  • CANNOT_BORROW(2, "不可借阅"):图书不可借阅

3.6 常量类(Constants)

3.6.1 Constants.java

Constants类定义了系统中使用的常量。

java 复制代码
public class Constants {
    // Session中存储用户信息的键
    public static final String SESSION_USER_KEY = "userInfo";
}

4. 数据库设计

根据代码分析,系统使用了两个主要的数据库表:

4.1 book_info表

存储图书信息的表,包含以下字段:

字段名 类型 说明
book_id INT 主键,图书ID
book_name VARCHAR 图书名称
author VARCHAR 作者
count INT 数量
price DOUBLE 价格
publish VARCHAR 出版社
status INT 状态(0-删除 1-正常 2-不可借阅)

4.2 user_info表

存储用户信息的表,包含以下字段:

字段名 类型 说明
user_id INT 主键,用户ID
user_name VARCHAR 用户名
password VARCHAR 密码

5. 系统功能分析

5.1 用户功能

  • 用户登录:验证用户名和密码,成功后将用户信息存入Session

5.2 图书管理功能

  • 添加图书:添加新的图书信息
  • 查询图书:分页查询图书列表
  • 图书详情:根据ID查询图书详细信息
  • 更新图书:修改图书信息
  • 删除图书:批量删除图书(逻辑删除)

6. 系统特点与优势

6.1 架构清晰

系统采用经典的Spring Boot MVC分层架构,各层职责明确,代码结构清晰,便于维护和扩展。

6.2 代码规范

代码风格统一,命名规范,注释详细,便于理解和维护。

6.3 数据校验

系统对输入数据进行了严格的校验,提高了系统的健壮性和安全性。

6.4 统一响应格式

系统使用ResultResponseResult类统一处理API响应,提供了标准化的响应格式,便于前端处理。

6.5 分页查询

系统实现了分页查询功能,提高了查询效率和用户体验。

7. 可改进之处

7.1 安全性

  • 密码存储:当前密码以明文方式存储,建议使用加密算法(如BCrypt)对密码进行加密
  • 权限控制:可以引入Spring Security实现更完善的权限控制

7.2 功能扩展

  • 图书借阅功能:增加图书借阅、归还等功能
  • 用户管理:增加用户注册、修改密码等功能
  • 图书分类:增加图书分类功能,便于图书管理和查询

7.3 性能优化

  • 缓存:引入Redis等缓存技术,提高查询效率
  • 索引:优化数据库索引,提高查询性能

8. 总结

该Spring Boot图书管理系统是一个典型的Web应用程序,采用了Spring Boot框架和MyBatis ORM工具,实现了图书的基本管理功能和用户登录功能。系统架构清晰,代码规范,具有良好的可维护性和扩展性。通过对该系统的分析,可以深入理解Spring Boot应用的开发模式和最佳实践。


参考资料

相关推荐
007php0072 分钟前
使用 Docker 安装 Elastic Stack 并重置本地密码
大数据·运维·后端·mysql·docker·eureka·jenkins
嘵奇3 分钟前
Spring Boot 断点续传实战:大文件上传不再怕网络中断
java·spring boot·后端
爱的叹息39 分钟前
AI推荐系统的详细解析 +推荐系统中滤泡效应(Filter Bubble)的详细解析+ 基于Java构建电商推荐系统的分步实现方案,结合机器学习与工程实践
java·人工智能·机器学习
勇哥java实战分享42 分钟前
聊聊四种实时通信技术:长轮询、短轮询、WebSocket 和 SSE
后端
sinat_2622921142 分钟前
Java面试实战:谢飞机的求职记 - Spring Boot、Redis与微服务技术问答解析
java·spring boot·redis·微服务·分布式事务
东方芷兰43 分钟前
Javase 基础入门 —— 02 基本数据类型
java·开发语言·笔记·spring·intellij-idea·idea
pwzs1 小时前
掌握常见 HTTP 方法:GET、POST、PUT 到 CONNECT 全面梳理
java·后端·http
chendilincd1 小时前
C++ 的史诗级进化:从C++98到C++20
java·c++·c++20
独行soc1 小时前
2025年渗透测试面试题总结-拷打题库08(题目+回答)
java·linux·运维·服务器·python·面试·职场和发展
~欸嘿1 小时前
pdf多文件合并
java·pdf