在高校教育管理信息化进程中,教材采购作为连接教学计划与课堂教学的关键环节,其管理效率直接影响教学活动的正常开展。传统依赖纸质单据、人工统计和分散沟通的采购模式存在信息滞后、数据易出错、流程不透明等痛点。针对这一需求,基于JSP+Servlet技术栈构建的教材采购管理系统实现了从教材需求申报、采购计划制定、供应商对接、订单执行到库存管理的全流程数字化管控。
系统采用经典的三层架构模式,表现层使用JSP动态页面技术结合HTML/CSS/JavaScript实现用户交互界面,业务逻辑层通过Servlet控制器处理请求并调用JavaBean组件完成业务规则验证,数据持久层则基于JDBC技术封装DAO模式操作MySQL数据库。这种架构确保了业务逻辑、数据访问和用户界面的分离,提高了系统的可维护性和扩展性。

数据库架构设计
系统采用13张数据表构建完整的业务数据模型,核心表包括用户信息表、教材信息表、采购订单表和库存记录表。每张表都设计了规范的主外键约束和索引策略,确保数据的一致性和查询效率。
用户信息表(user)设计体现了多角色权限管理的核心思路:
CREATE TABLE user (
user_id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(100) NOT NULL,
real_name VARCHAR(50) NOT NULL,
role ENUM('admin', 'teacher', 'student') NOT NULL,
department_id INT,
email VARCHAR(100),
phone VARCHAR(20),
status TINYINT DEFAULT 1,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login_time TIMESTAMP,
FOREIGN KEY (department_id) REFERENCES department(department_id)
);
该表通过role字段实现三种用户角色的区分,department_id外键关联院系信息表,支持按院系进行数据隔离。status字段支持账户的启用/禁用状态管理,last_login_time记录用户最后登录时间用于安全审计。
采购订单表(purchase_order)的设计展现了复杂的业务流程数据建模:
CREATE TABLE purchase_order (
order_id INT PRIMARY KEY AUTO_INCREMENT,
order_number VARCHAR(50) UNIQUE NOT NULL,
teacher_id INT NOT NULL,
book_id INT NOT NULL,
quantity INT NOT NULL CHECK (quantity > 0),
unit_price DECIMAL(10,2) NOT NULL,
total_amount DECIMAL(12,2) NOT NULL,
order_status ENUM('pending', 'approved', 'rejected', 'completed') DEFAULT 'pending',
approver_id INT,
approve_time TIMESTAMP NULL,
reject_reason TEXT,
supplier_id INT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expected_delivery_date DATE,
actual_delivery_date DATE,
FOREIGN KEY (teacher_id) REFERENCES user(user_id),
FOREIGN KEY (book_id) REFERENCES textbook(book_id),
FOREIGN KEY (approver_id) REFERENCES user(user_id),
FOREIGN KEY (supplier_id) REFERENCES supplier(supplier_id)
);
订单表通过order_status字段实现采购审批工作流的状态跟踪,包含价格、数量、金额等完整的业务字段,并通过多个外键关联确保数据的引用完整性。expected_delivery_date和actual_delivery_date字段支持到货时间的管理和统计。
核心业务功能实现
用户身份认证与权限控制
系统采用基于Session的身份认证机制,用户登录后服务器端创建会话并存储用户身份信息。权限控制通过过滤器(Filter)实现,对需要认证的请求路径进行拦截验证。
@WebFilter("/*")
public class AuthenticationFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);
String path = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length());
// 公开访问路径
if (path.startsWith("/login") || path.startsWith("/static/")) {
chain.doFilter(request, response);
return;
}
// 检查用户是否登录
if (session == null || session.getAttribute("currentUser") == null) {
httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");
return;
}
User currentUser = (User) session.getAttribute("currentUser");
// 基于角色的权限验证
if (!hasPermission(currentUser, path)) {
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "权限不足");
return;
}
chain.doFilter(request, response);
}
private boolean hasPermission(User user, String path) {
// 实现基于路径和角色的权限验证逻辑
return true;
}
}
教材信息管理模块
教材信息管理提供完整的CRUD操作,支持教材基本信息、库存状态、供应商信息的维护。管理员可以添加新教材、更新库存信息、设置采购参数等。
@WebServlet("/textbook/*")
public class TextbookServlet extends HttpServlet {
private TextbookDAO textbookDAO = new TextbookDAO();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getPathInfo();
switch (action) {
case "/add":
addTextbook(request, response);
break;
case "/update":
updateTextbook(request, response);
break;
case "/delete":
deleteTextbook(request, response);
break;
default:
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
private void addTextbook(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Textbook textbook = new Textbook();
textbook.setIsbn(request.getParameter("isbn"));
textbook.setBookName(request.getParameter("bookName"));
textbook.setAuthor(request.getParameter("author"));
textbook.setPublisher(request.getParameter("publisher"));
textbook.setEdition(request.getParameter("edition"));
textbook.setPrice(new BigDecimal(request.getParameter("price")));
textbook.setSupplierId(Integer.parseInt(request.getParameter("supplierId")));
textbookDAO.addTextbook(textbook);
request.setAttribute("message", "教材添加成功");
request.getRequestDispatcher("/textbook/list.jsp").forward(request, response);
} catch (Exception e) {
request.setAttribute("error", "添加教材失败: " + e.getMessage());
request.getRequestDispatcher("/textbook/add.jsp").forward(request, response);
}
}
}

采购订单审批工作流
采购订单审批是系统的核心业务流程,包含教师提交采购申请、管理员审批、供应商分配、订单执行状态跟踪等环节。系统通过状态机模式管理订单生命周期。
public class OrderService {
private OrderDAO orderDAO = new OrderDAO();
public void approveOrder(int orderId, int approverId, String comments) {
Connection conn = null;
try {
conn = DatabaseUtil.getConnection();
conn.setAutoCommit(false);
// 获取订单当前状态
PurchaseOrder order = orderDAO.getOrderById(orderId);
if (!"pending".equals(order.getOrderStatus())) {
throw new IllegalStateException("订单状态不正确,无法审批");
}
// 更新订单状态
orderDAO.updateOrderStatus(orderId, "approved", approverId, comments);
// 记录审批日志
AuditLogService.logApproval(approverId, orderId, "approved", comments);
// 触发库存预占操作
InventoryService.reserveInventory(order.getBookId(), order.getQuantity());
conn.commit();
} catch (Exception e) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
throw new RuntimeException("审批操作失败", e);
} finally {
DatabaseUtil.closeConnection(conn);
}
}
}
购物车与订单生成
教师和学生用户可以将所需教材加入购物车,系统支持批量生成采购订单。购物车数据存储在Session中,确保用户操作的连贯性。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>购物车</title>
</head>
<body>
<h2>我的购物车</h2>
<c:if test="${not empty cartItems}">
<table border="1">
<tr>
<th>教材名称</th>
<th>作者</th>
<th>出版社</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th>操作</th>
</tr>
<c:forEach var="item" items="${cartItems}">
<tr>
<td>${item.textbook.bookName}</td>
<td>${item.textbook.author}</td>
<td>${item.textbook.publisher}</td>
<td>¥${item.textbook.price}</td>
<td>
<input type="number" name="quantity" value="${item.quantity}"
min="1" onchange="updateQuantity(${item.textbook.bookId}, this.value)">
</td>
<td>¥${item.textbook.price * item.quantity}</td>
<td>
<button onclick="removeFromCart(${item.textbook.bookId})">删除</button>
</td>
</tr>
</c:forEach>
</table>
<div>总金额: ¥${totalAmount}</div>
<button onclick="submitOrder()">提交采购申请</button>
</c:if>
</body>
</html>

数据访问层设计
系统采用DAO模式封装所有数据库操作,提供统一的数据访问接口。BaseDAO抽象类封装了通用的CRUD操作方法,各实体DAO继承基类并实现特定业务逻辑。
public abstract class BaseDAO<T> {
protected Connection getConnection() throws SQLException {
return DatabaseUtil.getConnection();
}
protected List<T> executeQuery(String sql, ResultSetHandler<T> handler, Object... params) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
rs = pstmt.executeQuery();
return handler.handle(rs);
} catch (SQLException e) {
throw new RuntimeException("数据库查询失败", e);
} finally {
DatabaseUtil.closeResultSet(rs);
DatabaseUtil.closeStatement(pstmt);
DatabaseUtil.closeConnection(conn);
}
}
protected int executeUpdate(String sql, Object... params) {
// 实现更新操作
}
}
public class TextbookDAO extends BaseDAO<Textbook> {
private static final String INSERT_SQL = "INSERT INTO textbook " +
"(isbn, book_name, author, publisher, edition, price, supplier_id) " +
"VALUES (?, ?, ?, ?, ?, ?, ?)";
public void addTextbook(Textbook textbook) {
executeUpdate(INSERT_SQL,
textbook.getIsbn(), textbook.getBookName(), textbook.getAuthor(),
textbook.getPublisher(), textbook.getEdition(), textbook.getPrice(),
textbook.getSupplierId());
}
public Textbook getTextbookById(int bookId) {
String sql = "SELECT * FROM textbook WHERE book_id = ?";
List<Textbook> result = executeQuery(sql, new TextbookResultSetHandler(), bookId);
return result.isEmpty() ? null : result.get(0);
}
}
库存管理机制
库存管理模块实现实时库存跟踪、安全库存预警、库存调整记录等功能。系统通过触发器自动更新库存数量,确保数据的一致性。
DELIMITER $$
CREATE TRIGGER update_inventory_after_order_completion
AFTER UPDATE ON purchase_order
FOR EACH ROW
BEGIN
IF NEW.order_status = 'completed' AND OLD.order_status != 'completed' THEN
UPDATE inventory
SET current_stock = current_stock + NEW.quantity,
last_restock_date = NEW.actual_delivery_date
WHERE book_id = NEW.book_id;
END IF;
END$$
DELIMITER ;

系统优化与扩展方向
性能优化策略
- 数据库查询优化:对频繁查询的字段建立复合索引,如订单状态+创建时间的组合索引,提升查询性能
- 连接池配置:使用DBCP或HikariCP连接池管理数据库连接,减少连接创建开销
- 页面静态化:对教材目录等相对静态的内容生成静态页面,降低服务器压力
功能扩展建议
- 移动端适配:开发响应式界面或独立的移动应用,支持教师通过手机提交采购申请
- 供应商门户:为教材供应商提供外部接入接口,支持订单状态查询和发货信息回传
- 智能推荐:基于历史采购数据和课程信息,智能推荐合适的教材版本和供应商
技术架构升级
- 框架迁移:考虑从原生Servlet向Spring Boot框架迁移,获得更好的开发效率和生态支持
- 缓存集成:引入Redis缓存热点数据,如教材信息、用户权限数据等
- 异步处理:使用消息队列处理耗时的操作,如邮件通知、报表生成等
该系统通过严谨的架构设计和完整的业务功能实现,为高校教材采购管理提供了可靠的数字化解决方案。模块化的设计使得系统具有良好的可维护性和扩展性,为后续的功能增强和技术升级奠定了坚实基础。