- 系统功能设计
- 项目结构
- 核心代码实现 (包含详细注释)
- 运行与扩展
系统功能设计
一个基础的图书管理系统应该包含以下核心功能:

- 图书管理 (增删改查)
- 添加图书: 输入图书信息(如:ISBN、书名、作者、出版社、库存数量)并保存。
- 删除图书: 根据图书ID或书名查找并删除指定图书。
- 修改图书: 查找图书并修改其信息(如:修改库存)。
- 查询图书:
- 按ID精确查询。
- 按书名或作者模糊查询。
- 显示所有图书列表。
- 数据持久化
程序关闭后,图书数据不能丢失,我们将使用简单的文件存储(如 CSV 或 JSON 格式)来实现。
- 图形用户界面
使用 Java Swing 设计直观、易用的界面。
项目结构
为了代码的清晰和可维护性,我们采用 MVC(Model-View-Controller)的简化思想来组织代码。
BookManagementSystem/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── model/
│ │ │ │ └── Book.java // 图书实体类 (Model)
│ │ │ ├── controller/
│ │ │ │ └── BookManager.java // 图书业务逻辑控制器
│ │ │ ├── ui/
│ │ │ │ ├── MainFrame.java // 主窗口 (View)
│ │ │ │ ├── AddBookDialog.java // 添加图书对话框 (View)
│ │ │ │ └── BookTablePanel.java // 图书列表表格面板 (View)
│ │ │ └── Main.java // 程序入口
│ │ └── resources/
│ │ └── books.csv // 数据存储文件
│ └── test/
│ └── ...
└── pom.xml // Maven 项目文件 (可选,但推荐)
核心代码实现
1 Model (图书实体类)
src/main/java/model/Book.java
这是图书数据的基本结构。
package model;
import java.io.Serializable;
// 实现Serializable接口,以便对象可以写入文件
public class Book implements Serializable {
private String id; // 图书ID (ISBN)
private String title; // 书名
private String author; // 作者
private String publisher; // 出版社
private int quantity; // 库存数量
public Book(String id, String title, String author, String publisher, int quantity) {
this.id = id;
this.title = title;
this.author = author;
this.publisher = publisher;
this.quantity = quantity;
}
// Getters and Setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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 getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
@Override
public String toString() {
return "Book{" +
"id='" + id + '\'' +
", title='" + title + '\'' +
", author='" + author + '\'' +
", publisher='" + publisher + '\'' +
", quantity=" + quantity +
'}';
}
}
2 Controller (图书管理器)
src/main/java/controller/BookManager.java
这是核心业务逻辑,负责图书的增删改查以及数据文件的读写。
package controller;
import model.Book;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class BookManager {
private List<Book> books;
private static final String FILE_PATH = "resources/books.csv";
public BookManager() {
this.books = new ArrayList<>();
loadBooks();
}
// 从文件加载图书数据
private void loadBooks() {
File file = new File(FILE_PATH);
if (!file.exists()) {
return; // 文件不存在,不执行任何操作
}
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(",");
if (parts.length == 5) {
books.add(new Book(parts[0], parts[1], parts[2], parts[3], Integer.parseInt(parts[4])));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 保存图书数据到文件
public void saveBooks() {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(FILE_PATH))) {
for (Book book : books) {
writer.write(book.getId() + "," + book.getTitle() + "," + book.getAuthor() + "," + book.getPublisher() + "," + book.getQuantity());
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 添加图书
public boolean addBook(Book book) {
if (findBookById(book.getId()) != null) {
return false; // 图书ID已存在
}
books.add(book);
saveBooks(); // 添加后立即保存
return true;
}
// 根据 ID 删除图书
public boolean deleteBook(String id) {
Book book = findBookById(id);
if (book != null) {
books.remove(book);
saveBooks(); // 删除后立即保存
return true;
}
return false;
}
// 根据 ID 查找图书
public Book findBookById(String id) {
return books.stream().filter(b -> b.getId().equals(id)).findFirst().orElse(null);
}
// 根据 书名 或 作者 模糊查询
public List<Book> searchBooks(String keyword) {
if (keyword == null || keyword.trim().isEmpty()) {
return new ArrayList<>(books); // 返回所有图书
}
String lowerKeyword = keyword.toLowerCase();
return books.stream()
.filter(b -> b.getTitle().toLowerCase().contains(lowerKeyword) || b.getAuthor().toLowerCase().contains(lowerKeyword))
.collect(Collectors.toList());
}
// 获取所有图书
public List<Book> getAllBooks() {
return new ArrayList<>(books);
}
}
3 View (用户界面)
3.1 主窗口
src/main/java/ui/MainFrame.java
这是应用程序的主窗口,集成了菜单栏和图书列表。
package ui;
import controller.BookManager;
import model.Book;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
public class MainFrame extends JFrame {
private BookManager bookManager;
private BookTablePanel bookTablePanel;
private JMenuBar menuBar;
public MainFrame() {
bookManager = new BookManager();
setTitle("图书管理系统");
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); // 居中显示
initMenuBar();
initUI();
}
private void initMenuBar() {
menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("文件");
JMenuItem exitItem = new JMenuItem("退出");
exitItem.addActionListener(e -> System.exit(0));
fileMenu.add(exitItem);
JMenu editMenu = new JMenu("编辑");
JMenuItem addItem = new JMenuItem("添加图书");
addItem.addActionListener(e -> showAddBookDialog());
JMenuItem deleteItem = new JMenuItem("删除选中图书");
deleteItem.addActionListener(e -> deleteSelectedBook());
editMenu.add(addItem);
editMenu.add(deleteItem);
JMenu searchMenu = new JMenu("查询");
JMenuItem searchAllItem = new JMenuItem("显示所有图书");
searchAllItem.addActionListener(e -> bookTablePanel.refreshBooks(bookManager.getAllBooks()));
JMenuItem searchItem = new JMenuItem("搜索图书");
searchItem.addActionListener(e -> showSearchDialog());
searchMenu.add(searchAllItem);
searchMenu.add(searchItem);
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(searchMenu);
setJMenuBar(menuBar);
}
private void initUI() {
bookTablePanel = new BookTablePanel();
bookTablePanel.refreshBooks(bookManager.getAllBooks());
add(bookTablePanel, BorderLayout.CENTER);
}
private void showAddBookDialog() {
AddBookDialog dialog = new AddBookDialog(this, "添加图书");
dialog.setVisible(true);
if (dialog.isConfirmed()) {
Book newBook = dialog.getBook();
if (bookManager.addBook(newBook)) {
bookTablePanel.refreshBooks(bookManager.getAllBooks());
JOptionPane.showMessageDialog(this, "添加成功!", "成功", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(this, "图书ID已存在!", "错误", JOptionPane.ERROR_MESSAGE);
}
}
}
private void deleteSelectedBook() {
String selectedId = bookTablePanel.getSelectedBookId();
if (selectedId == null) {
JOptionPane.showMessageDialog(this, "请先选择要删除的图书!", "提示", JOptionPane.WARNING_MESSAGE);
return;
}
int option = JOptionPane.showConfirmDialog(this, "确定要删除ID为 " + selectedId + " 的图书吗?", "确认删除", JOptionPane.YES_NO_OPTION);
if (option == JOptionPane.YES_OPTION) {
if (bookManager.deleteBook(selectedId)) {
bookTablePanel.refreshBooks(bookManager.getAllBooks());
JOptionPane.showMessageDialog(this, "删除成功!", "成功", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(this, "删除失败!", "错误", JOptionPane.ERROR_MESSAGE);
}
}
}
private void showSearchDialog() {
String keyword = JOptionPane.showInputDialog(this, "请输入书名或作者关键词:", "搜索图书", JOptionPane.PLAIN_MESSAGE);
if (keyword != null) {
List<Book> searchResults = bookManager.searchBooks(keyword);
bookTablePanel.refreshBooks(searchResults);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
new MainFrame().setVisible(true);
});
}
}
3.2 图书列表表格面板
src/main/java/ui/BookTablePanel.java
这是一个可重用的面板,用于以表格形式展示图书列表。
package ui;
import model.Book;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.util.List;
public class BookTablePanel extends JPanel {
private JTable table;
private DefaultTableModel tableModel;
public BookTablePanel() {
setLayout(new BorderLayout());
initTable();
}
private void initTable() {
// 定义表格列
String[] columnNames = {"ID", "书名", "作者", "出版社", "库存"};
tableModel = new DefaultTableModel(columnNames, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false; // 所有单元格不可编辑
}
};
table = new JTable(tableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 单行选择
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
}
// 刷新表格数据
public void refreshBooks(List<Book> books) {
tableModel.setRowCount(0); // 清空现有数据
for (Book book : books) {
Object[] rowData = {
book.getId(),
book.getTitle(),
book.getAuthor(),
book.getPublisher(),
book.getQuantity()
};
tableModel.addRow(rowData);
}
}
// 获取当前选中的图书ID
public String getSelectedBookId() {
int selectedRow = table.getSelectedRow();
if (selectedRow != -1) {
return tableModel.getValueAt(selectedRow, 0).toString();
}
return null;
}
}
3.3 添加图书对话框
src/main/java/ui/AddBookDialog.java
一个模态对话框,用于输入新图书的信息。
package ui;
import model.Book;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AddBookDialog extends JDialog {
private JTextField idField, titleField, authorField, publisherField, quantityField;
private Book newBook;
private boolean confirmed = false;
public AddBookDialog(Frame owner, String title) {
super(owner, title, true); // true 表示模态对话框
initUI();
}
private void initUI() {
JPanel panel = new JPanel(new GridLayout(5, 2, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.add(new JLabel("图书ID (ISBN):"));
idField = new JTextField();
panel.add(idField);
panel.add(new JLabel("书名:"));
titleField = new JTextField();
panel.add(titleField);
panel.add(new JLabel("作者:"));
authorField = new JTextField();
panel.add(authorField);
panel.add(new JLabel("出版社:"));
publisherField = new JTextField();
panel.add(publisherField);
panel.add(new JLabel("库存数量:"));
quantityField = new JTextField();
panel.add(quantityField);
JButton confirmButton = new JButton("确定");
JButton cancelButton = new JButton("取消");
JPanel buttonPanel = new JPanel();
buttonPanel.add(confirmButton);
buttonPanel.add(cancelButton);
confirmButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (validateInput()) {
newBook = new Book(
idField.getText(),
titleField.getText(),
authorField.getText(),
publisherField.getText(),
Integer.parseInt(quantityField.getText())
);
confirmed = true;
dispose();
}
}
});
cancelButton.addActionListener(e -> dispose());
add(panel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(getOwner());
}
private boolean validateInput() {
if (idField.getText().trim().isEmpty() || titleField.getText().trim().isEmpty() || quantityField.getText().trim().isEmpty()) {
JOptionPane.showMessageDialog(this, "ID、书名和库存不能为空!", "输入错误", JOptionPane.ERROR_MESSAGE);
return false;
}
try {
int quantity = Integer.parseInt(quantityField.getText());
if (quantity < 0) {
JOptionPane.showMessageDialog(this, "库存数量不能为负数!", "输入错误", JOptionPane.ERROR_MESSAGE);
return false;
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "库存数量必须是整数!", "输入错误", JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
public boolean isConfirmed() {
return confirmed;
}
public Book getBook() {
return newBook;
}
}
4 程序入口
src/main/java/Main.java
package ui;
public class Main {
public static void main(String[] args) {
MainFrame.main(args); // 直接调用MainFrame的main方法,因为它包含了主逻辑
}
}
运行与扩展
如何运行
-
环境准备: 确保你已安装 JDK 8 或更高版本。
-
项目结构: 按照上面的目录结构创建文件和包。
-
编译运行:
-
如果你使用 IDE (如 IntelliJ IDEA 或 Eclipse),直接创建一个 Java 项目,将代码复制到对应包中,然后运行
Main.java。 -
如果使用命令行:
# 确保在 src 目录的父目录下 # 编译所有 java 文件 javac -d . src/main/java/**/*.java # 运行主类 java -cp . ui.Main
-
-
首次运行: 程序会自动在
src/main/resources/目录下创建books.csv文件来存储数据。
可能的扩展方向
这个基础版本已经非常完整,你可以在此基础上进行扩展:
- 用户管理: 添加管理员和普通用户角色,普通用户只能查询,管理员可以进行增删改。
- 借阅功能: 添加“借阅”和“归还”按钮,当借阅时,减少图书库存,并记录借阅人、借阅时间等信息,这需要一个新的
BorrowRecord类。 - 更友好的UI:
- 使用
JXDatePicker来选择日期(用于借阅记录)。 - 使用图标美化按钮和菜单。
- 实现分页显示,当图书数量很多时,一页一页地展示。
- 使用
- 更强大的数据存储:
- 将 CSV 文件替换为 JSON 或 XML,它们在结构化数据上更灵活。
- 进阶:集成 数据库 (如 MySQL, SQLite),使用 JDBC 连接数据库,将
BookManager中的文件操作替换为 SQL 操作,这是最专业、最健壮的方案。
- 高级搜索: 实现多条件组合查询(同时按作者和出版社搜索)。
- 数据统计: 添加一个功能,可以统计各类图书的数量、最受欢迎的图书等,并用图表展示,可以使用 JFreeChart 等库。
