標籤:
這種視圖結構可能被用在菜單,或者某種體現分類的資訊上面等等。今天就讓我們來探討下怎麼從後端去實現這樣的一個內容!如果是Java使用者那就比較熟悉這其中的文法了。
首先看下前端瀏覽器的效果:
從其中不難發現,這是個分類資訊展示,而且具有多級效果,業務上是需要無限極的特點的,上級和下級具有關聯關係的。那麼這種結構需要什麼樣的資料庫表結構呢?
資料庫內需要存在以上4個資訊以上才能很方便地展示出剛才的效果,至少目前來看是擁有足夠的資訊了。那麼接下來咱們的業務層如何去處理?
下面我定義了一個transform方法,用於取出資料庫內所有的分類資料,並且轉換為相對應的TreeNode對象的集合。這個TreeNode集合是一個彼此有關係的對象集合,TreeNode至少擁有如此的屬性:id、text、children,其中children又是一個TreeNode對象的集合,代表子分類對象的集合。
public List<TreeNode> transform() {
// Gets all categories
List<Category> categories = categoryDao.selectWhole();
// Do sorting this categories,by level attribute value.The level 0 is
// root category.
categories.sort(new Comparator<Category>() {
@Override
public int compare(Category o1, Category o2) {
Integer level1 = o1.getLevel();
Integer level2 = o2.getLevel();
// The min level will be sorted to the top
return level1.compareTo(level2);
}
});
// Initial list of tree nodes
List<TreeNode> treeNodes = new ArrayList<>();
for (Category category : categories) {
// Transform the category to a new treenode
TreeNode newTreeNode = new TreeNode(category.getName());
newTreeNode.setId(category.getId());
newTreeNode.setSuperId(category.getSuperId());
// If the category‘s super id is null,that means it is a root
// category.
if (category.getSuperId() == null) {
treeNodes.add(newTreeNode);
} else {// Else call this method for next step
treePlant(treeNodes, newTreeNode);
}
}
return treeNodes;
}
transform方法內,首先調用資料訪問層的方法將分類資料全部取出來,並返回一個領域對象的集合,這個領域對象跟資料庫的結構是屬於對應關係的,肯定是不能直接拿來用在顯示上面的,這裡並沒有使用像Hibernate那種的ORM架構,可以理解為使用的就是原生的JDBC技術。接下來調用了該集合的sort方法用於排序集合內的對象,且從裡面的內容可以看出,排序依據是領域對象的level屬性,也就是層級。在此處,說下層級是什麼意思,最頂級的分類可以將其層級置為0,第二層級置為1,以此類推。添加層級屬性的話,是對處理層次關係是有很大的協助的,此處就用上了。經過這樣排序的操作,那麼最終這個集合內是一個層級最小排最前面的集合。為什麼進行排序?後面就會知道。接下來定義一個TreeNode新的空的集合,用於方法返回。迴圈遍曆領域對象的集合,並將當前迴圈到的對象轉換為一個新的TreeNode對象,分別將編號和父編號賦值到TreeNode。然後對領域對象進行一個判斷,判斷父編號是否為空白,如果為空白的話,就直接將其放入返回對象集合內,即TreeNode集合。反之調用treePlant方法:
private void treePlant(List<TreeNode> treeNodes, TreeNode newTreeNode) {
// Else it is not a root category,then find the super category and plant
// the category in it.
for (TreeNode treeNode : treeNodes) {
if (treeNode.getId().equals(newTreeNode.getSuperId())) {
treeNode.getChildren().add(newTreeNode);
return;
}
treePlant(treeNode.getChildren(), newTreeNode);
}
}
treePlant方法,用於將新的TreeNode對象正確放入到TreeNode對象集合內。如果找到編號為父編號的對象,那麼就將其放入到父TreeNode的children對象集合內,以表明這種關係。其實要想這個方法運行正常的話,得考慮幾個問題,首先是傳入的treeNodes對象也就是TreeNode對象集合必須存在頂級分類(在資料庫存在資料的情況下),這也就是為什麼在transform方法內要首先將父編號為空白的放入treeNodes對象。其次就是層次關係的問題,假設有這樣一種情況,衣服是頂級分類,其下有上衣、褲子等,這些是二級分類,再往下有夾克,這個屬於三級分類,屬於上衣分類。在這裡只是舉個例子,如果不用設計一個層次屬性的話,會出現什麼情況呢?在調用treePlant方法的時候,有可能會出現丟失分類資料的情況!衣服分類在傳入之前就已經放入參數treeNodes對象中,這個不用懷疑,在執行到內部迴圈的時候,此時如果迴圈到的分類是夾克,它屬於上衣這個分類,你此時不能保證上衣這個分類已經被放入treeNodes對象中,也就是說,夾克這個三級分類有可能丟失。這就是為什麼要設計一個level屬性即層次層級。經過transform方法內排序處理,層次數越小的排在最前面,也就不會出現丟失分類的情況。
那麼此時,已經得到一個TreeNode對象的集合,這個集合正是前端需要的資料,裡面的結構也正好符合相關架構的要求,在這裡,我用的是ExtJS。
這個解決方案是本人親自摸索出來並應用而沒有問題。如有更好的解決方案,請聯絡我告知,感恩不盡!
產品分類樹形展示的Java實現