杰瑞科技汇

Java图书管理系统如何实现核心功能?

Java课程设计:图书管理系统

项目概述

本项目旨在开发一个功能完善的、基于控制台的图书管理系统,系统使用Java语言进行开发,采用面向对象的思想,通过文件存储数据,实现图书的增、删、改、查等基本功能,并具备用户友好的交互界面,通过本项目的实践,可以巩固和深化对Java基础、面向对象编程、集合框架、I/O流以及异常处理等核心知识点的理解和应用。

Java图书管理系统如何实现核心功能?-图1
(图片来源网络,侵删)

功能需求分析

系统主要分为两大模块:图书管理模块用户交互模块

1 图书管理模块 (核心功能)

  1. 添加图书

    • 输入图书信息:ISBN、书名、作者、出版社、出版年份、库存数量。
    • 系统自动生成一个唯一的ID。
    • 将新图书信息保存到数据文件中。
    • 约束:ISBN不能重复,库存数量不能为负数。
  2. 删除图书

    Java图书管理系统如何实现核心功能?-图2
    (图片来源网络,侵删)
    • 通过图书ID或ISBN进行查找。
    • 确认后删除该图书信息。
    • 约束:如果图书不存在,给出提示。
  3. 修改图书信息

    • 通过图书ID或ISBN进行查找。
    • 允许用户修改除ID外的所有信息(书名、作者、出版社、年份、库存)。
    • 修改后更新数据文件。
    • 约束:如果图书不存在,给出提示。
  4. 查询图书

    • 按ID查询:精确查询,快速定位。
    • 按ISBN查询:精确查询。
    • 按书名查询:模糊查询,支持部分匹配。
    • 按作者查询:模糊查询。
    • 显示所有图书:以列表形式展示所有图书信息。
  5. 数据持久化

    • 系统启动时,从文件(如 books.dat)中加载所有图书信息。
    • 每次对图书信息进行增、删、改操作后,自动将数据写回文件,确保数据不丢失。

2 用户交互模块

Java图书管理系统如何实现核心功能?-图3
(图片来源网络,侵删)
  1. 主菜单

    • 显示系统功能列表,引导用户进行操作。
    • 包含:添加、删除、修改、查询、显示所有、退出系统等选项。
  2. 输入处理

    • 对用户的输入进行合法性校验(年份必须是数字,库存不能为负)。
    • 对非法输入进行捕获和处理,给出友好提示,避免程序崩溃。
  3. 界面友好性

    • 操作提示清晰。
    • 执行结果(成功/失败)有明确的反馈。

技术选型

  • 编程语言:Java (推荐使用 JDK 8 或更高版本)
  • 开发环境:IntelliJ IDEA / Eclipse
  • 核心技术
    • 面向对象:使用 class 来定义 BookBookManager
    • 集合框架:使用 ArrayList<Book> 来在内存中存储和管理图书对象,因为它动态扩容,便于增删改。
    • I/O流:使用 ObjectInputStreamObjectOutputStream 来实现对象的序列化和反序列化,从而将 ArrayList 对象直接存入和读出文件。
    • 异常处理:使用 try-catch 块处理可能发生的 IOException, ClassNotFoundException 等异常。

系统设计

1 类图设计

+---------------------+
|      Book           |
+---------------------+
| - id: String        |
| - isbn: String      | String     |
| - author: String    |
| - publisher: String |
| - year: int         |
| - stock: int        |
+---------------------+
| + getId(): String   |
| + getIsbn(): String |
| + ... (getters)    |
| + setId(String): void |
| + ... (setters)    |
| + toString(): String|
+---------------------+
          ^
          |
          | uses / contains
          |
+---------------------+
|    BookManager      |
+---------------------+
| - bookList: ArrayList<Book> |
| - dataFile: File    |
+---------------------+
| + addBook(Book): void |
| + deleteBook(String): boolean |
| + updateBook(Book): boolean |
| + findBookById(String): Book |
| + findBookByIsbn(String): Book|
| + findBooksByTitle(String): ArrayList<Book>|
| + listAllBooks(): void |
| + saveToFile(): void  |
| + loadFromFile(): void |
+---------------------+
          ^
          |
          | creates
          |
+---------------------+
|      MainApp        |
+---------------------+
| + main(String[]): void |
+---------------------+

2 核心类设计

  1. Book.java (图书实体类)

    • 属性id, isbn, title, author, publisher, year, stock,所有属性设为 private,并提供 publicgettersetter 方法。
    • 方法
      • 构造方法:无参构造和全参构造。
      • toString() 方法:用于格式化输出图书信息。
  2. BookManager.java (图书管理器类)

    • 属性
      • bookList: ArrayList<Book>,用于在内存中存放所有图书。
      • dataFile: File 对象,指向数据存储文件(如 books.dat)。
    • 方法
      • loadFromFile(): 系统启动时调用,从文件加载数据到 bookList
      • saveToFile(): 每次增删改后调用,将 bookList 保存到文件。
      • addBook(Book book): 添加图书,并检查ID和ISBN唯一性。
      • deleteBook(String idOrIsbn): 删除图书。
      • updateBook(Book book): 更新图书信息。
      • findBookById(String id): 根据ID精确查找。
      • findBookByIsbn(String isbn): 根据ISBN精确查找。
      • findBooksByTitle(String keyword): 根据书名模糊查找。
      • listAllBooks(): 遍历并打印所有图书。
  3. MainApp.java (主程序入口类)

    • 方法main(String[] args)
    • 功能
      1. 创建 BookManager 实例。
      2. 调用 bookManager.loadFromFile() 加载数据。
      3. 进入一个 while 循环,显示主菜单。
      4. 根据用户输入,调用 BookManager 的相应方法。
      5. 处理用户输入,并进行异常捕获。
      6. 用户选择退出时,调用 bookManager.saveToFile() 保存数据,并结束程序。

核心代码实现

1 Book.java

import java.io.Serializable;
// 实现Serializable接口,以便对象可以被序列化
public class Book implements Serializable {
    private String id;
    private String isbn;
    private String title;
    private String author;
    private String publisher;
    private int year;
    private int stock;
    // 无参构造
    public Book() {}
    // 全参构造
    public Book(String id, String isbn, String title, String author, String publisher, int year, int stock) {
        this.id = id;
        this.isbn = isbn;
        this.title = title;
        this.author = author;
        this.publisher = publisher;
        this.year = year;
        this.stock = stock;
    }
    // Getters and Setters
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getIsbn() { return isbn; }
    public void setIsbn(String isbn) { this.isbn = isbn; }
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public String getAuthor() { return author; }
    public void setAuthor(String author) { this.author = author; }
    public String getPublisher() { return publisher; }
    public void setPublisher(String publisher) { this.publisher = publisher; }
    public int getYear() { return year; }
    public void setYear(int year) { this.year = year; }
    public int getStock() { return stock; }
    public void setStock(int stock) { this.stock = stock; }
    @Override
    public String toString() {
        return String.format("ID: %s, ISBN: %s, 书名: %s, 作者: %s, 出版社: %s, 年份: %d, 库存: %d",
                id, isbn, title, author, publisher, year, stock);
    }
}

2 BookManager.java

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public class BookManager implements Serializable {
    private ArrayList<Book> bookList;
    private final File dataFile = new File("books.dat");
    public BookManager() {
        bookList = new ArrayList<>();
        loadFromFile();
    }
    // 从文件加载数据
    public void loadFromFile() {
        if (dataFile.exists()) {
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(dataFile))) {
                bookList = (ArrayList<Book>) ois.readObject();
                System.out.println("数据加载成功!");
            } catch (IOException | ClassNotFoundException e) {
                System.err.println("加载文件时出错: " + e.getMessage());
                bookList = new ArrayList<>(); // 如果加载失败,初始化一个空列表
            }
        } else {
            System.out.println("数据文件不存在,将创建新文件。");
        }
    }
    // 保存数据到文件
    public void saveToFile() {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(dataFile))) {
            oos.writeObject(bookList);
            // System.out.println("数据保存成功!"); // 可以选择不打印,以免干扰用户
        } catch (IOException e) {
            System.err.println("保存文件时出错: " + e.getMessage());
        }
    }
    // 添加图书
    public void addBook(Book book) {
        // 检查ID和ISBN是否已存在
        if (findBookById(book.getId()) != null || findBookByIsbn(book.getIsbn()) != null) {
            System.out.println("添加失败:ID或ISBN已存在!");
            return;
        }
        bookList.add(book);
        saveToFile();
        System.out.println("图书添加成功!");
    }
    // 删除图书
    public boolean deleteBook(String idOrIsbn) {
        Book book = findBookById(idOrIsbn);
        if (book == null) {
            book = findBookByIsbn(idOrIsbn);
        }
        if (book != null) {
            bookList.remove(book);
            saveToFile();
            System.out.println("图书删除成功!");
            return true;
        } else {
            System.out.println("未找到ID或ISBN为 " + idOrIsbn + " 的图书!");
            return false;
        }
    }
    // 更新图书
    public boolean updateBook(Book updatedBook) {
        for (int i = 0; i < bookList.size(); i++) {
            Book book = bookList.get(i);
            if (book.getId().equals(updatedBook.getId())) {
                // 检查新ISBN是否与其他图书冲突
                if (!book.getIsbn().equals(updatedBook.getIsbn()) && findBookByIsbn(updatedBook.getIsbn()) != null) {
                    System.out.println("更新失败:新ISBN已存在!");
                    return false;
                }
                bookList.set(i, updatedBook);
                saveToFile();
                System.out.println("图书信息更新成功!");
                return true;
            }
        }
        System.out.println("未找到ID为 " + updatedBook.getId() + " 的图书!");
        return false;
    }
    // 查找方法...
    public Book findBookById(String id) {
        return bookList.stream().filter(book -> book.getId().equals(id)).findFirst().orElse(null);
    }
    public Book findBookByIsbn(String isbn) {
        return bookList.stream().filter(book -> book.getIsbn().equals(isbn)).findFirst().orElse(null);
    }
    public List<Book> findBooksByTitle(String keyword) {
        return bookList.stream().filter(book -> book.getTitle().toLowerCase().contains(keyword.toLowerCase())).collect(Collectors.toList());
    }
    public void listAllBooks() {
        if (bookList.isEmpty()) {
            System.out.println("图书馆中没有图书。");
        } else {
            System.out.println("===== 图书列表 =====");
            bookList.forEach(System.out::println);
            System.out.println("===================");
        }
    }
    // 生成唯一ID的辅助方法
    public String generateId() {
        return "B" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }
}

3 MainApp.java

import java.util.InputMismatchException;
import java.util.List;
import java.util.Scanner;
public class MainApp {
    private static final Scanner scanner = new Scanner(System.in);
    private static final BookManager bookManager = new BookManager();
    public static void main(String[] args) {
        while (true) {
            showMenu();
            int choice = getChoice();
            processChoice(choice);
        }
    }
    private static void showMenu() {
        System.out.println("\n===== 图书管理系统 =====");
        System.out.println("1. 添加图书");
        System.out.println("2. 删除图书");
        System.out.println("3. 修改图书");
        System.out.println("4. 查询图书");
        System.out.println("5. 显示所有图书");
        System.out.println("0. 退出系统");
        System.out.print("请输入您的选择: ");
    }
    private static int getChoice() {
        try {
            return scanner.nextInt();
        } catch (InputMismatchException e) {
            scanner.next(); // 清除错误的输入
            System.out.println("输入无效,请输入数字!");
            return -1; // 返回一个无效值
        }
    }
    private static void processChoice(int choice) {
        scanner.nextLine(); // 消耗掉nextInt()后的换行符
        switch (choice) {
            case 1:
                addBookUI();
                break;
            case 2:
                deleteBookUI();
                break;
            case 3:
                updateBookUI();
                break;
            case 4:
                searchBookUI();
                break;
            case 5:
                bookManager.listAllBooks();
                break;
            case 0:
                System.out.println("感谢使用,系统退出。");
                bookManager.saveToFile(); // 确保退出前保存
                System.exit(0);
            default:
                System.out.println("无效的选择,请重新输入!");
        }
    }
    // UI交互方法...
    private static void addBookUI() {
        System.out.println("--- 添加新图书 ---");
        System.out.print("请输入ISBN: ");
        String isbn = scanner.nextLine();
        System.out.print("请输入书名: ");
        String title = scanner.nextLine();
        System.out.print("请输入作者: ");
        String author = scanner.nextLine();
        System.out.print("请输入出版社: ");
        String publisher = scanner.nextLine();
        System.out.print("请输入出版年份: ");
        int year = getIntegerInput();
        System.out.print("请输入库存数量: ");
        int stock = getIntegerInput();
        if (year <= 0 || stock < 0) {
            System.out.println("输入错误:年份和库存必须为有效正数!");
            return;
        }
        String id = bookManager.generateId();
        Book newBook = new Book(id, isbn, title, author, publisher, year, stock);
        bookManager.addBook(newBook);
    }
    private static void deleteBookUI() {
        System.out.println("--- 删除图书 ---");
        System.out.print("请输入要删除的图书ID或ISBN: ");
        String idOrIsbn = scanner.nextLine();
        bookManager.deleteBook(idOrIsbn);
    }
    private static void updateBookUI() {
        System.out.println("--- 修改图书信息 ---");
        System.out.print("请输入要修改的图书ID: ");
        String id = scanner.nextLine();
        Book book = bookManager.findBookById(id);
        if (book == null) {
            System.out.println("未找到该ID的图书!");
            return;
        }
        System.out.println("找到图书: " + book);
        System.out.print("请输入新书名 (留空则不修改): ");
        String newTitle = scanner.nextLine();
        if (!newTitle.isEmpty()) book.setTitle(newTitle);
        System.out.print("请输入新作者 (留空则不修改): ");
        String newAuthor = scanner.nextLine();
        if (!newAuthor.isEmpty()) book.setAuthor(newAuthor);
        // ... 可以继续添加其他字段的修改逻辑
        bookManager.updateBook(book);
    }
    private static void searchBookUI() {
        System.out.println("--- 查询图书 ---");
        System.out.println("1. 按ID查询");
        System.out.println("2. 按ISBN查询");
        System.out.println("3. 按书名查询");
        System.out.print("请选择查询方式: ");
        int searchChoice = getChoice();
        scanner.nextLine(); // 消耗换行符
        switch (searchChoice) {
            case 1:
                System.out.print("请输入图书ID: ");
                String id = scanner.nextLine();
                Book book = bookManager.findBookById(id);
                if (book != null) {
                    System.out.println("查询结果: " + book);
                } else {
                    System.out.println("未找到该ID的图书。");
                }
                break;
            case 2:
                System.out.print("请输入图书ISBN: ");
                String isbn = scanner.nextLine();
                Book bookByIsbn = bookManager.findBookByIsbn(isbn);
                if (bookByIsbn != null) {
                    System.out.println("查询结果: " + bookByIsbn);
                } else {
                    System.out.println("未找到该ISBN的图书。");
                }
                break;
            case 3:
                System.out.print("请输入书名关键词: ");
                String keyword = scanner.nextLine();
                List<Book> books = bookManager.findBooksByTitle(keyword);
                if (!books.isEmpty()) {
                    System.out.println("查询结果:");
                    books.forEach(System.out::println);
                } else {
                    System.out.println("未找到包含关键词的图书。");
                }
                break;
            default:
                System.out.println("无效的选择。");
        }
    }
    private static int getIntegerInput() {
        while (true) {
            try {
                return scanner.nextInt();
            } catch (InputMismatchException e) {
                scanner.next(); // 清除错误输入
                System.out.print("输入无效,请输入一个整数: ");
            }
        }
    }
}

项目扩展与优化 (进阶方向)

如果你想让项目更上一层楼,可以考虑以下扩展:

  1. 引入数据库:将文件存储替换为MySQL或SQLite数据库,这需要学习JDBC,是更企业级的做法。
  2. 图形用户界面:使用Java Swing或JavaFX开发GUI版本,提供更直观的用户体验。
  3. 用户角色管理:增加“管理员”和“普通用户”角色,管理员拥有所有权限,普通用户只有查询和借阅(需要增加借阅记录表)权限。
  4. 借阅与归还功能
    • 增加一个 User 类和一个 LoanRecord 类。
    • LoanRecord 记录谁、在什么时候、借了哪本书、什么时候归还。
    • 修改图书的 stockavailableStock,借书时减少,还书时增加。
  5. 排序功能:在显示图书列表时,可以按书名、出版年份等字段进行排序。
  6. 单元测试:使用 JUnit 为 BookManager 中的核心方法(如 addBook, deleteBook)编写单元测试,确保代码质量。

部署与运行指南

  1. 环境准备:确保你的电脑上已安装JDK和开发环境(如IDEA)。
  2. 创建项目:在IDEA中创建一个新的Java项目。
  3. 创建类:在 src 目录下创建 Book.java, BookManager.java, 和 MainApp.java 三个类,并将上述代码分别复制进去。
  4. 运行:运行 MainApp.javamain 方法。
  5. 操作:根据控制台提示进行操作,第一次运行后,会在项目根目录下自动生成一个 books.dat 文件,用于存储数据。

这个方案为你提供了一个非常坚实的基础,你可以直接在此基础上进行编码和调试,完成你的课程设计,祝你项目顺利!

分享:
扫描分享到社交APP
上一篇
下一篇