在傳統JSP專案中實現樹形商品分類管理,核心在於資料庫遞迴查詢與前端樹狀元件(如zTree)的JSON資料結構對接。本文提供完整實作範例:資料表設計、遞迴查詢SQL/DAO、Controller組裝JSON、JSP整合zTree。
CREATE TABLE category (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
parent_id BIGINT DEFAULT 0 COMMENT '0=根節點',
sort_order INT DEFAULT 0,
is_leaf TINYINT(1) DEFAULT 1 COMMENT '1=葉子節點(可掛商品)',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
<select id="selectAll" resultType="com.example.model.Category">
SELECT id, name, parent_id, sort_order, is_leaf
FROM category
ORDER BY parent_id, sort_order
</select>
public List<ZTreeNode> buildZTreeNodes() {
List<Category> all = categoryDao.selectAll();
Map<Long, ZTreeNode> nodeMap = new HashMap<>();
// 1. 建立所有節點
for (Category c : all) {
ZTreeNode node = new ZTreeNode();
node.setId(c.getId());
node.setpId(c.getParentId());
node.setName(c.getName());
node.setOpen(c.getParentId() == 0); // 根節點預設展開
node.setIsParent(!c.getIsLeaf());
nodeMap.put(c.getId(), node);
}
// 2. 組裝父子關係(zTree只需id/pId,前端自動建樹)
return new ArrayList<>(nodeMap.values());
}
ZTreeNode僅需包含id、pId、name、open、isParent等屬性,zTree會自動根據pId建立樹結構。
@GetMapping("/category/tree")
@ResponseBody
public List<ZTreeNode> categoryTree() {
return categoryService.buildZTreeNodes();
}
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<link rel="stylesheet" href="${ctx}/static/ztree/css/zTreeStyle/zTreeStyle.css">
<script src="${ctx}/static/ztree/js/jquery.ztree.all.min.js"></script>
</head>
<body>
<ul id="categoryTree" class="ztree"></ul>
<script>
var setting = {
view: { dblClickExpand: false, showLine: true },
data: { simpleData: { enable: true, idKey: "id", pIdKey: "pId", rootPId: 0 } },
callback: {
onClick: function(event, treeId, treeNode) {
if (treeNode.isParent) {
$.fn.zTree.getZTreeObj("categoryTree").expandNode(treeNode);
} else {
// 葉子節點:載入商品列表
loadProducts(treeNode.id);
}
}
}
};
$.get("${ctx}/category/tree", function(nodes) {
$.fn.zTree.init($("#categoryTree"), setting, nodes);
});
function loadProducts(categoryId) {
$("#productList").load("${ctx}/product/list?categoryId=" + categoryId);
}
</script>
<div id="productList">請選擇分類查看商品</div>
</body>
</html>
// 新增
$.post("${ctx}/category/add", {name: "新分類", parentId: selectedNode.id}, function(res) {
if (res.success) $.fn.zTree.getZTreeObj("categoryTree").reAsyncChildNodes(selectedNode, "refresh");
});
// 刪除(需先檢查是否有子節點或商品)
$.post("${ctx}/category/delete", {id: node.id}, function(res) {
if (res.success) $.fn.zTree.getZTreeObj("categoryTree").removeNode(node);
});
async: {enable: true, url: "/category/children"}),點擊父節點時才請求子節點。DEL cache_key失效重建。掌握「扁平列表 → pId映射 → zTree簡單資料模式」這條路徑,即可在任何JSP/Spring MVC專案中快速落地樹形管理功能。