基于JSP+Servlet的图书信息管理系统 - 源码深度解析

JavaScriptHTMLCSSMySQLJSP+Servlet
2026-02-273 浏览

文章摘要

本项目是基于JSP和Servlet技术栈构建的图书信息管理系统,旨在为中小型图书馆或书店提供一个稳定、易用的核心业务管理工具。其核心业务价值在于将传统依赖纸质记录或零散Excel表格的图书管理模式,转变为集中化、标准化的数字流程,有效解决了图书信息混乱、检索效率低下、库存更新不及时等核心痛点。系统通...

在传统图书管理场景中,管理员常常面临信息记录零散、检索效率低下、库存更新不及时等核心痛点。纸质登记簿或零散的Excel表格不仅容易造成数据不一致,也难以支持快速的模糊查询和动态统计。针对这一市场需求,我们设计并实现了一套基于JSP+Servlet技术栈的图书信息管理解决方案,该系统被命名为“智慧图书库”。

智慧图书库采用经典的J2EE MVC架构模式,实现了表示层、控制层、业务逻辑层和数据访问层的清晰分离。表示层由JSP页面构成,负责数据的动态渲染和用户交互;控制层通过Servlet组件接收和转发HTTP请求;业务逻辑层封装核心业务规则;数据访问层则基于JDBC技术实现对MySQL数据库的标准化操作。这种分层架构确保了系统的高内聚、低耦合特性,为后续功能扩展和维护提供了良好的基础。

数据库架构设计与核心表分析

系统共设计5张核心数据表,其中books表作为系统的数据核心,其结构设计体现了严谨的业务考量:

CREATE TABLE books (
    book_id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(200) NOT NULL,
    author VARCHAR(100) NOT NULL,
    publisher VARCHAR(100),
    publish_date DATE,
    isbn VARCHAR(20) UNIQUE,
    category VARCHAR(50),
    price DECIMAL(10,2),
    stock_quantity INT DEFAULT 0,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

该表的设计亮点在于:book_id采用自增主键确保唯一性;isbn字段设置唯一约束符合图书行业标准;price字段使用DECIMAL(10,2)类型精确存储金额;created_timeupdated_time两个时间戳字段实现了数据的全生命周期追踪。特别是updated_time字段通过ON UPDATE CURRENT_TIMESTAMP特性,在记录修改时自动更新时间,为数据审计提供了便利。

用户权限管理通过users表实现:

CREATE TABLE users (
    user_id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(100) NOT NULL,
    role ENUM('admin','operator') DEFAULT 'operator',
    last_login_time DATETIME,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

该表采用ENUM类型严格限制用户角色为管理员或操作员两种类型,通过last_login_time字段记录用户最后登录时间,为系统安全审计提供数据支持。密码字段预留100字符长度,为后续加密算法升级预留空间。

核心功能实现解析

1. 图书检索功能

系统提供多条件组合检索能力,支持按书名、作者、出版社等关键字段进行模糊查询。前端通过表单提交查询参数,后端Servlet接收并处理请求:

@WebServlet("/book/search")
public class BookSearchServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String keyword = request.getParameter("keyword");
        String category = request.getParameter("category");
        
        BookDAO bookDAO = new BookDAO();
        List<Book> bookList = bookDAO.searchBooks(keyword, category);
        
        request.setAttribute("bookList", bookList);
        RequestDispatcher dispatcher = request.getRequestDispatcher("/book-list.jsp");
        dispatcher.forward(request, response);
    }
}

数据访问层通过预编译Statement防止SQL注入,同时使用LIKE操作符实现模糊匹配:

public class BookDAO {
    public List<Book> searchBooks(String keyword, String category) {
        List<Book> books = new ArrayList<>();
        String sql = "SELECT * FROM books WHERE title LIKE ? AND category LIKE ?";
        
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            
            stmt.setString(1, "%" + keyword + "%");
            stmt.setString(2, "%" + category + "%");
            
            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                Book book = extractBookFromResultSet(rs);
                books.add(book);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return books;
    }
}

图书检索界面

2. 图书信息维护模块

图书信息的增删改查操作通过统一的BookService类进行业务逻辑封装:

public class BookService {
    private BookDAO bookDAO = new BookDAO();
    
    public boolean addBook(Book book) {
        // 数据验证逻辑
        if (book.getTitle() == null || book.getTitle().trim().isEmpty()) {
            throw new IllegalArgumentException("图书标题不能为空");
        }
        if (book.getPrice().compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("图书价格不能为负数");
        }
        
        return bookDAO.insertBook(book) > 0;
    }
    
    public boolean updateBookStock(int bookId, int quantity) {
        if (quantity < 0) {
            throw new IllegalArgumentException("库存数量不能为负数");
        }
        return bookDAO.updateStock(bookId, quantity);
    }
}

编辑功能通过预加载原始数据确保数据一致性:

@WebServlet("/book/edit")
public class BookEditServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        int bookId = Integer.parseInt(request.getParameter("id"));
        BookDAO bookDAO = new BookDAO();
        Book book = bookDAO.getBookById(bookId);
        
        if (book != null) {
            request.setAttribute("book", book);
            request.getRequestDispatcher("/book-edit.jsp").forward(request, response);
        } else {
            response.sendRedirect("/book/list?error=图书不存在");
        }
    }
}

图书编辑界面

3. 库存管理功能

库存管理采用乐观锁机制防止并发更新问题,通过版本号控制确保数据一致性:

public class InventoryService {
    public boolean updateInventory(int bookId, int quantity, int version) {
        String sql = "UPDATE books SET stock_quantity = ?, version = version + 1 " +
                    "WHERE book_id = ? AND version = ?";
        
        try (Connection conn = DatabaseUtil.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            
            stmt.setInt(1, quantity);
            stmt.setInt(2, bookId);
            stmt.setInt(3, version);
            
            int affectedRows = stmt.executeUpdate();
            return affectedRows > 0;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }
}

库存预警功能通过定时任务检测低库存图书:

public class InventoryAlertTask extends TimerTask {
    private static final int LOW_STOCK_THRESHOLD = 5;
    
    @Override
    public void run() {
        BookDAO bookDAO = new BookDAO();
        List<Book> lowStockBooks = bookDAO.getLowStockBooks(LOW_STOCK_THRESHOLD);
        
        if (!lowStockBooks.isEmpty()) {
            sendLowStockAlert(lowStockBooks);
        }
    }
}

库存管理界面

实体模型与业务逻辑

系统核心实体类采用JavaBean规范设计,确保数据的封装性和可序列化性:

public class Book implements Serializable {
    private int bookId;
    private String title;
    private String author;
    private String publisher;
    private Date publishDate;
    private String isbn;
    private String category;
    private BigDecimal price;
    private int stockQuantity;
    private Date createdTime;
    private Date updatedTime;
    
    // 完整的getter和setter方法
    public int getBookId() { return bookId; }
    public void setBookId(int bookId) { this.bookId = bookId; }
    
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    
    // 其他getter/setter方法...
    
    @Override
    public String toString() {
        return "Book{bookId=" + bookId + ", title='" + title + "'}";
    }
}

业务逻辑层通过服务类封装复杂的业务规则,如图书入库时的数据验证流程:

public class BookInventoryService {
    public BookInventoryResult addBookToInventory(Book book, int initialQuantity) {
        BookInventoryResult result = new BookInventoryResult();
        
        // 验证图书基本信息
        if (!validateBookInfo(book)) {
            result.setSuccess(false);
            result.setMessage("图书信息验证失败");
            return result;
        }
        
        // 检查ISBN是否已存在
        if (bookDAO.isIsbnExists(book.getIsbn())) {
            result.setSuccess(false);
            result.setMessage("ISBN已存在");
            return result;
        }
        
        // 执行入库操作
        boolean insertSuccess = bookDAO.insertBook(book);
        if (insertSuccess) {
            boolean stockSuccess = inventoryDAO.updateStock(book.getBookId(), initialQuantity);
            result.setSuccess(stockSuccess);
            result.setMessage(stockSuccess ? "入库成功" : "库存更新失败");
        }
        
        return result;
    }
}

前端交互与用户体验

JSP页面通过JSTL标签库和EL表达式实现数据的动态渲染,避免在页面中嵌入Java代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<table class="book-table">
    <thead>
        <tr>
            <th>书名</th>
            <th>作者</th>
            <th>出版社</th>
            <th>库存</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody>
        <c:forEach var="book" items="${bookList}">
            <tr>
                <td>${book.title}</td>
                <td>${book.author}</td>
                <td>${book.publisher}</td>
                <td class="stock-${book.stockQuantity > 5 ? 'sufficient' : 'low'}">
                    ${book.stockQuantity}
                </td>
                <td>
                    <a href="/book/edit?id=${book.bookId}">编辑</a>
                    <a href="/book/delete?id=${book.bookId}" 
                       onclick="return confirm('确定删除吗?')">删除</a>
                </td>
            </tr>
        </c:forEach>
    </tbody>
</table>

图书列表界面

表单验证通过JavaScript增强用户体验,在提交前进行客户端验证:

function validateBookForm() {
    const title = document.getElementById('title').value.trim();
    const author = document.getElementById('author').value.trim();
    const price = document.getElementById('price').value;
    
    if (title === '') {
        alert('请输入图书标题');
        return false;
    }
    
    if (author === '') {
        alert('请输入作者姓名');
        return false;
    }
    
    if (isNaN(price) || parseFloat(price) < 0) {
        alert('请输入有效的价格');
        return false;
    }
    
    return true;
}

系统安全与性能优化

数据库连接通过连接池管理,提高系统性能并确保资源有效利用:

public class DatabaseUtil {
    private static DataSource dataSource;
    
    static {
        try {
            Context context = new InitialContext();
            dataSource = (DataSource) context.lookup("java:comp/env/jdbc/BookDB");
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
    
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
}

用户会话管理通过Filter实现访问控制:

@WebFilter("/*")
public class AuthenticationFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        String path = httpRequest.getRequestURI();
        
        // 公开路径允许直接访问
        if (path.endsWith("login.jsp") || path.endsWith("login")) {
            chain.doFilter(request, response);
            return;
        }
        
        HttpSession session = httpRequest.getSession(false);
        if (session == null || session.getAttribute("user") == null) {
            httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");
            return;
        }
        
        chain.doFilter(request, response);
    }
}

用户登录界面

未来优化方向

  1. 引入全文搜索引擎:集成Elasticsearch实现更强大的图书检索功能,支持分词、同义词、拼音搜索等高级特性,提升检索准确性和用户体验。

  2. 实现分布式架构:通过Spring Cloud微服务框架重构系统,将用户管理、图书管理、库存管理等模块拆分为独立服务,提高系统的可扩展性和容错能力。

  3. 增加数据分析模块:集成Apache Spark或Flink框架,对图书借阅数据、销售数据进行分析,生成阅读趋势分析、热门图书推荐等数据洞察报告。

  4. 开发移动端应用:基于React Native或Flutter技术开发跨平台移动应用,方便管理员随时随地管理图书库存和处理借阅事务。

  5. 实现区块链存证:对于珍贵图书或重要交易记录,利用区块链技术实现不可篡改的存证功能,增强系统的审计和追溯能力。

智慧图书库系统通过严谨的架构设计、完善的业务功能实现和良好的用户体验,为中小型图书管理场景提供了完整的数字化解决方案。系统的模块化设计和标准化编码规范为后续的功能扩展和技术升级奠定了坚实基础。

本文关键词
JSPServlet图书信息管理系统源码解析MVC架构

上下篇

上一篇
没有更多文章
下一篇
没有更多文章