最近做项目,由于好多地方需要树形显示,所以需要封装一个树形结构的显示,将代码重复降到最低。树形结构的显示用的是dwz框架中自带的。
需要树形结构显示的类:Organization、Module,只列出二者的公共属性,其它属性不列,
@Entity
@Table(name = "security_organization")
public class Organization{
private static final long serialVersionUID = 1775351000271333679L;
@Id
@GeneratedValue(generator = "hibernateuuidgenerator")
@GenericGenerator(name = "hibernateuuidgenerator", strategy = "uuid")
protected String id;
private String name;
@ManyToOne()
@JoinColumn(name="pid")
private Organization parent;
@OneToMany(mappedBy="parent",fetch=FetchType.EAGER)
private List<Organization> children;
private boolean isleaf;
//其它属性
}
@Entity
@Table(name="security_module")
public class Module{
/** 描述 */
private static final long serialVersionUID = -6926690440815291509L;
@Id
@GeneratedValue(generator = "hibernateuuidgenerator")
@GenericGenerator(name = "hibernateuuidgenerator", strategy = "uuid")
protected String id;
private String name;
@ManyToOne()
@JoinColumn(name="pid")
private Module parent;
@OneToMany(mappedBy="parent",fetch=FetchType.EAGER)
private List<Module> children;
private boolean isleaf;
//其它属性
}
大家可以看到,里面列的都是树所必须的属性:id、父id、是否为叶子结点,还可以考虑再往里面加。其实除了parent和children外,其它的都可以提到一个类里,这样,就可以再减少代码的重复。
下面再来再来看看我对生成树代码的封装:
public class GenerateTree {
private String target = "navTab";
private String style = "tree";
public String generate(String style, String parentURL, String sonURL, String target,
String rel, Object parent) {
StringBuffer sbTreeHTML = new StringBuffer();
if (style.equals("")) {
style = this.style;
}
if (target.equals("")) {
target = this.target;
}
if (parent == null) {
return "";
}
try {
sbTreeHTML.append("<ul class='" + style + "'>");
sbTreeHTML.append("<li><a href='" + (isIsleaf(parent) ? sonURL : parentURL)
+ "?id=" + getId(parent) + "' target='" + target + "' rel='" + rel
+ "'>" + getName(parent) + "</a>");
//如果子不为空,那么对子进行遍历
if (getChildren(parent) != null && getChildren(parent).size() > 0) {
sbTreeHTML.append(generateSon(style, parentURL, sonURL, target, rel,
getChildren(parent)));
}
sbTreeHTML.append("</li>");
sbTreeHTML.append("</ul>");
} catch (Exception e) {
return "";
}
return sbTreeHTML.toString();
}
private String generateSon(String style, String parentURL, String sonURL,
String target, String rel, List<Object> objects)
throws IllegalArgumentException, SecurityException, IllegalAccessException,
InvocationTargetException, NoSuchMethodException {
StringBuffer sbTreeHTML = new StringBuffer();
sbTreeHTML.append("<ul>");
for (Iterator<Object> iter = objects.iterator(); iter.hasNext();) {
Object tree = iter.next();
sbTreeHTML.append("<li><a href='" + (isIsleaf(tree) ? sonURL : parentURL)
+ "?id=" + getId(tree) + "' target='" + target + "' rel='" + rel
+ "'>" + getName(tree) + "</a>");
//如果不为空,对其进行递归
if (getChildren(tree) != null && getChildren(tree).size() > 0) {
sbTreeHTML.append(generateSon(style, parentURL, sonURL, target, rel,
getChildren(tree)));
}
sbTreeHTML.append("</li>");
}
sbTreeHTML.append("</ul>");
return sbTreeHTML.toString();
}
//获取对象的id
private String getId(Object o) throws IllegalArgumentException, SecurityException,
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return (String) o.getClass().getDeclaredMethod("getId").invoke(o);
}
//获取对象的children
private List<Object> getChildren(Object o) throws IllegalArgumentException,
SecurityException, IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
return (List<Object>) o.getClass().getDeclaredMethod("getChildren").invoke(o);
}
//获取对象的isleaf
private boolean isIsleaf(Object o) throws IllegalArgumentException,
SecurityException, IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
return Boolean.parseBoolean((String) o.getClass().getDeclaredMethod("isIsleaf")
.invoke(o));
}
//获取对象的name
private String getName(Object o) throws IllegalArgumentException, SecurityException,
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return (String) o.getClass().getDeclaredMethod("getName").invoke(o);
}
}
生成是生成了,那么应该怎样调用呢?再来看下面的吧:
public String generate(){
GenerateTree gt=new GenerateTree();
Module module=new Module();
module.setId("");
String treeModule=gt.generate("", "parentURL", "sonURL", "", "jbsx", module);
Organization org=new Organization();
org.setId("");
String treeOrg=gt.generate("", "parentURL", "sonURL", "", "jbsx", module);
request.setAttribute("treeModule", treeModule);
request.setAttribute("treeOrg", treeOrg);
return "success";
}
看到调用,不知细心、耐心的你是否已经发现,这个树形结构代码生成具有很好的扩展性:
若现在又有一个需要树形显示:Tree,那么Tree只需要按着开关写的属性名进行扩展,那么就可以用封装好的方法生成树形结构代码。这样,递归只需要出现一次即可。
经过这次的封装,我感觉提取需要的是一个过程,而提取的实现,需要的是知识面的宽阔。一如如果不是这次项目的封装,我还不知道参数后面可以加三个点呢。
封装的过程是痛苦的,但结果是美好的~~