最近的項目中遇到了一個含有大量數據的樹結構的展示,不要跟我說什麼樹都是數據量不大的之類的話。大不大我能控制嗎?
我能控制的只是怎麼用更好的方法把遇到的問題解決了。
代碼都在下面了,基本已經可以說是通用的了,誰有用的話直接複製走,改吧改吧就能用。而卻算法我也已經進行了大量的優化。all是樹所有節點,in是選中節點,combotreeModel是用來反射的模型,可有可無,不用模型直接用字符串也行。
@RequestMapping(params = "setnornBusiness")
@ResponseBody
public List setPFunction(HttpServletRequest request,
ComboTree comboTree, HttpSession session) {
CriteriaQuery cq = new CriteriaQuery(TreeNornBusiness.class);
cq.addOrder("cmdsort", SortDirection.asc);
cq.eq("isuse", "1");
List treeNornBusinessList = systemService.getListByCriteriaQuery(
cq, false);
List comboTrees;
ComboTreeModel comboTreeModel = new ComboTreeModel("id",
"name", "nornBusinessPid");
//獲取已有指令
String nornuserid = String.valueOf(session.getAttribute("nornuserid"));
List cmdtreeList = systemService.findByProperty(NornCmdtreeEntity.class, "nornuserid", nornuserid);
comboTrees = systemService.ComboTree(treeNornBusinessList, comboTreeModel, cmdtreeList);
return comboTrees;
}
/**
* 根據模型生成ComboTree JSON
*
* @param all全部對象
* @param in已擁有的對象
* @param comboTreeModel模型
* @return
*/
public List ComboTree(List all, ComboTreeModel comboTreeModel, List in) {
Set inIDs = new HashSet();
if (in != null) {
for (Object o : in) {
if (o != null) {
ReflectHelper reflectHelper = new ReflectHelper(o);
String id = oConvertUtils.getString(reflectHelper.getMethodValue("businessid"));
inIDs.add(id);
}
}
}
List trees = new ArrayList();//頂級節點集合
Set pIds = new HashSet();
Map> pIdMap = new HashMap>();
for (Object obj : all) {
// ComboTree comboTree = new ComboTree();
ComboTree comboTree = myComboTree(obj, comboTreeModel, inIDs);
if (comboTree.getpId() == "") {//如果pid==null則是頂級節點
trees.add(comboTree);
} else {
boolean add = pIds.add(comboTree.getpId());
if (add) {//如果pId添加進去了則說明第一次
List comboTrees = new ArrayList();
comboTrees.add(comboTree);
pIdMap.put(comboTree.getpId(), comboTrees);
} else {//否則這個pId之前就已經被添加過了
List comboTrees = pIdMap.get(comboTree.getpId());
comboTrees.add(comboTree);
pIdMap.put(comboTree.getpId(), comboTrees);
}
}
}
if (trees != null) {
for (ComboTree tree : trees) {
createResultTree(tree, pIdMap);
}
}
return trees;
}
/**
* @LiYuKun 2017/7/31 13:50 構建一個節點
* @param obj
* @param comboTreeModel
* @param inIDs
* @return
*/
private ComboTree myComboTree(Object obj, ComboTreeModel comboTreeModel, Set inIDs) {
ComboTree tree = new ComboTree();
Map attributes = new HashMap();
ReflectHelper reflectHelper = new ReflectHelper(obj);
String id = oConvertUtils.getString(reflectHelper.getMethodValue(comboTreeModel.getIdField()));
tree.setId(id);
tree.setpId(oConvertUtils.getString(reflectHelper.getMethodValue(comboTreeModel.getpId())));
tree.setText(oConvertUtils.getString(reflectHelper.getMethodValue(comboTreeModel.getTextField())));
if (comboTreeModel.getSrcField() != null) {
attributes.put("href", oConvertUtils.getString(reflectHelper.getMethodValue(comboTreeModel.getSrcField())));
tree.setAttributes(attributes);
}
if (inIDs == null) {
} else {
if (inIDs.size() > 0) {
boolean add = inIDs.add(id);//爲true 添加成功了,則說明該節點沒有在被選中;爲false則說明已經被選中了
if (!add) {
tree.setChecked(true);
}
}
}
return tree;
}
public class ReflectHelper {
private Class cls;
/**
* 傳過來的對象
*/
private Object obj;
/**
* 存放get方法
*/
private Hashtable getMethods = null;
/**
* 存放set方法
*/
private Hashtable setMethods = null;
/**
* 定義構造方法 -- 一般來說是個pojo
*
* @param o
* 目標對象
*/
public ReflectHelper(Object o) {
obj = o;
initMethods();
}
/**
*
* @desc 初始化
*/
public void initMethods() {
getMethods = new Hashtable();
setMethods = new Hashtable();
cls = obj.getClass();
Method[] methods = cls.getMethods();
// 定義正則表達式,從方法中過濾出getter / setter 函數.
String gs = "get(\\w+)";
Pattern getM = Pattern.compile(gs);
String ss = "set(\\w+)";
Pattern setM = Pattern.compile(ss);
// 把方法中的"set" 或者 "get" 去掉
String rapl = "$1";
String param;
for (int i = 0; i < methods.length; ++i) {
Method m = methods[i];
String methodName = m.getName();
if (Pattern.matches(gs, methodName)) {
param = getM.matcher(methodName).replaceAll(rapl).toLowerCase();
getMethods.put(param, m);
} else if (Pattern.matches(ss, methodName)) {
param = setM.matcher(methodName).replaceAll(rapl).toLowerCase();
setMethods.put(param, m);
} else {
// org.jeecgframework.core.util.LogUtil.info(methodName + " 不是getter,setter方法!");
}
}
}
/**
*
* @desc 調用set方法
*/
public boolean setMethodValue(String property,Object object) {
Method m = setMethods.get(property.toLowerCase());
if (m != null) {
try {
// 調用目標類的setter函數
m.invoke(obj, object);
return true;
} catch (Exception ex) {
org.jeecgframework.core.util.LogUtil.info("invoke getter on " + property + " error: " + ex.toString());
return false;
}
}
return false;
}
/**
*
* @desc 調用set方法
*/
public Object getMethodValue(String property) {
Object value=null;
Method m = getMethods.get(property.toLowerCase());
if (m != null) {
try {
/**
* 調用obj類的setter函數
*/
value=m.invoke(obj, new Object[] {});
} catch (Exception ex) {
org.jeecgframework.core.util.LogUtil.info("invoke getter on " + property + " error: " + ex.toString());
}
}
return value;
}
}
/**
* @param comboTree
* @param pIdMap
* @LiYuKun 2017/7/31 8:13,遞歸填充樹結構,填充完之後即爲要返回的數據
*/
private void createResultTree(ComboTree comboTree, Map> pIdMap) {
if (pIdMap.get(comboTree.getId()) != null) {
comboTree.setChildren(pIdMap.get(comboTree.getId()));
if (pIdMap.get(comboTree.getId()) != null) {
for (ComboTree tree : pIdMap.get(comboTree.getId())) {
createResultTree(tree, pIdMap);
}
}
}
}