做项目的时候有这样的需求,我们需要在下拉列表中把部门的结构以树形结构的形式给显示出来。原型如下:
我们的架构是SSH(struts2),下面将实现过程(代码都是一些核心代码)和大家分享:
一、代码:
Jsp:
<%@taglib prefix="s" uri="/struts-tags" %> <!--显示表单内容--> <divid=MainArea> <formaction="department_${id==null?'add':'edit'}.action"> <s:hiddenname="id" /> <divclass="ItemBlock_Title1"> <!--信息说明<DIV CLASS="ItemBlock_Title1"> <IMGBORDER="0" WIDTH="4" HEIGHT="7"SRC="${pageContext.request.contextPath}/style/blue/images/item_point.gif"/> 部门信息 </DIV> --> </div> <!--表单内容显示 --> <divclass="ItemBlockBorder"> <divclass="ItemBlock"> <tablecellpadding="0" cellspacing="0"class="mainForm"> <tr> <td>上级部门</td> <!-- <td><select>--> <!-- <s:iteratorvalue="%{#list}"> --> <!-- <optionvalue="${id}">${name}</option> --> <!-- </s:iterator>--> <!-- </select>--> <!-- </td>--> <td><s:select cssClass="SelectStyle"name="parentId" list="#list" listKey="id"listValue="name" headerKey=""headerValue="==请选择部门==" ></s:select></td> </tr> <tr> <td>部门名称</td> <td><s:textfieldname="name" cssClass="InputStyle" /> *</td> </tr> <tr> <td>职能说明</td> <td><s:textareaname="description" cssClass="TextareaStyle" /> </td> </tr> </table> </div> </div> <!--表单操作 --> <divid="InputDetailBar"> <inputtype="image" src="${pageContext.request.contextPath}/style/images/save.png"/> <ahref="department_list.action;"><img src="${pageContext.request.contextPath}/style/images/goBack.png"/> </a> </div> </form> </div>
Action:
/** * 编辑页面 */ publicString editUI() { //获取顶层部门节点 List<Department>listTopDepartments=serviceDepartment.findTopDepartment(); //获取树形集合 List<Department>departmentTree=DepartmentUtils.getTree(listTopDepartments); ActionContext.getContext().put("list",departmentTree); //查询当前记录 Departmentdepartment = serviceDepartment.getById(model.getId()); ActionContext.getContext().getValueStack().push(department); if(department.getParent()!=null){ parentId=department.getParent().getId(); } return"saveUI"; } //父id, //由于我们的department中不存在此属性,但是我们回显要用到,在此声明即可用到,即可回显数据(struts2决定的) publicLong parentId; /** * */ publicLong getParentId() { returnparentId; } /** * @param parentId the parentId to set */ publicvoid setParentId(Long parentId) { this.parentId= parentId; }
注:struts2标签+ognl(有了struts2的标签ognl才有意义。)表达式很强大;ognl表达式(用来设置和获取java对象的属性),struts2能使ognl的内容在页面显示。另外struts2对httpServletRequest进行了封装,所以el表达式
Service:查询父节点
returngetSession().createQuery("From Department d where d.parent isnull").list();
实现树形工具类:(核心->递归)
/** * 部门工具类 * @author V-HUXJ * */ publicclass DepartmentUtils { //department树 publicstatic List<Department> getTree(List<Department> topDepartment) { List<Department>lisDepartmentTTree = new ArrayList<Department>(); //组装树(递归调用) combTree(topDepartment,"┠", lisDepartmentTTree); returnlisDepartmentTTree; } publicstatic void combTree(Collection<Department> topList, String pre, List<Department>lisDepartmentTTree) { //加载一个颗完整的树 for(Department top : topList) { Departmentdepartment = new Department(); department.setId(top.getId()); department.setName(pre+top.getName()); //加入到集合中 lisDepartmentTTree.add(department); //加载所有孩子 combTree(top.getChildren()," "+pre, lisDepartmentTTree); } }
注:树的核心就是从顶点出发,直到子类的叶子节点;这样循环出所有的树。
实现方式是递归;它主要控制树的形状和样式。
二、总结
当我们面对复杂问题的时候,一定要找它的核心(全局观)(比如树的核心无非就是递归每一个节点),复杂的问题简单化,这样问题不解决都难啊!