最近由於項目需要,做一個樹形動態菜單,用extjs3 來做,結合springMVC,實現從後臺動態的加載數據形成權限菜單。
一、數據表設計
首先是數據庫的設計,數據庫表是一張權限表(即菜單表),我把它設計成一張遞歸表,實現能顯示父級菜單和子菜單的樹形菜單,
表的設計如下:
使用pri_Id爲外鍵,引用本表的主鍵,實現一張遞歸表。
二、Java代碼中po類的設計
po類的設計對應數據表中的數據(除了外鍵),用於做傳送數據用。
private Integer id;//節點id
private String text;//節點名稱
private boolean leaf;//是否爲子節點
private String url;//節點點擊的請求路徑
private String cls;//節點的圖標,folder還是file
private Privilige parent;//父級菜單
private Set<Privilige> children = new HashSet<Privilige>();//子菜單
//getter...setter
注意字段的名字不能變,因爲返回json數據給前臺時extjs會自動識別並加載。
三、前臺extjs的jsp界面
Ext.QuickTips.init();//顯示提示信息
//樹加載器
var treeLoader = new Ext.tree.TreeLoader(
{
//獲取數據庫的遠程地址
dataUrl:"${pageContext.request.contextPath }/Menu/showAllMenu"
});
//當點擊節點時傳遞節點id到服務器端上
treeLoader.on("beforeload",function(treeLoader,node){
this.baseParams.nodeId = node.id;
});
//定義樹
var tree = new Ext.tree.TreePanel({
id : 'tree',
animate : true,
autoScroll : true,
containerScroll : true,
lines : true,
rootVisible:false,//不顯示根節點
loader:treeLoader,//加載後臺數據的樹加載器
expanded:true,
//根節點要用AsyncTreeNode
root: new Ext.tree.AsyncTreeNode({
expanded: true,
text:"系統菜單",
id:"0",
leaf:false
})
});
四、設計privilige接口及實現類
public interface PrivilegeService {
/**
* 根據父級菜單的id獲取其下的子菜單
*/
List<Privilige> getMenuByParentId(Integer pid);
/**
* 判斷用戶是否擁有某項權限
* @param sysOper 登陸的操作員
* @param menuId 權限對應的id
*/
boolean hasPermission(Systemoper sysOper,Integer menuId);
/**
* 判斷角色是否擁有某項權限
*/
boolean hasPermission(Role role,Integer menuId);
/**
* 返回全部權限(菜單)數據給前臺
* @param noteId
* @return
*/
List<Privilige> getAllPriviliges(Integer noteId);
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import net.seehope.dao.PriviligeDao;
import net.seehope.po.Privilige;
import net.seehope.po.Role;
import net.seehope.po.Systemoper;
import net.seehope.service.PrivilegeService;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class PrivilegeServiceImpl implements PrivilegeService {
@Resource
private SessionFactory sessionFactory;
@Resource
private PriviligeDao priviligeDao;
public Session getSession(){
return sessionFactory.getCurrentSession();
}
@SuppressWarnings("unchecked")
@Override
public List getAllPriviliges(Integer noteId) {
List<Privilige> topList =
(List<Privilige>) getSession()
.createQuery("From Privilige p where p.parent IS NULL").list();
//存放返回的數據集
List<Map> list = new ArrayList<Map>();
Map map = null;
if(noteId == 0){//首次加載樹
//遍歷所有的根節點
for (Privilige privilige : topList) {
map = new HashMap();
map.put("id", privilige.getId());
map.put("text", privilige.getText());
map.put("leaf", privilige.isLeaf());
map.put("cls", privilige.getCls());
list.add(map);
}
}else{//非首次加載樹
List<Privilige> leafMenu = getMenuByParentId(noteId);//根據父節點id獲取其下子節點
Map m = null;
//加載子節點
for (Privilige leafPri : leafMenu) {
m = new HashMap();
m.put("id", leafPri.getId());
m.put("text", leafPri.getText());
m.put("leaf", leafPri.isLeaf());
m.put("cls", leafPri.getCls());
m.put("url", leafPri.getUrl());
list.add(m);
}
}
return list;
}
@SuppressWarnings("unchecked")
@Override
public List<Privilige> getMenuByParentId(Integer pid) {
String hql = "FROM Privilige p where p.parent.id = ?";
List<Privilige> list = getSession().createQuery(hql)
.setParameter(0, pid).list();
return list;
}
@Override
public boolean hasPermission(Systemoper sysOper, Integer menuId) {
//拿到操作員的所有角色
for(Role role : sysOper.getSysrole()){
//拿到角色的所有權限
for(Privilige pri : role.getPriviliges()){
if(menuId.equals(pri.getId())){
return true;
}
}
}
return false;
}
@Override
public boolean hasPermission(Role role, Integer menuId) {
if(role.getPriviliges() != null && role.getPriviliges().size()>0){
for(Privilige pri : role.getPriviliges()){
if(menuId.equals(pri.getId())){
return true;
}
}
}
return false;
}
}
五、設計springMVC的控制類
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import net.seehope.po.Privilige;
import net.seehope.service.PrivilegeService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 操作權限的action
* @author 毛健宇
* 創建日期: 2014-11-3 下午9:34:50
* @version 1.0.0
*/
@Controller
@RequestMapping("Menu")
public class PrivilegeAction {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(PrivilegeAction.class);
@Resource
private PrivilegeService privilegeServiceImpl;
@RequestMapping(value="showAllMenu")
public @ResponseBody List getTopPrivileges(HttpServletRequest request){
//獲得父節點的id
int nid = Integer.valueOf(request.getParameter("nodeId"));
//獲取所有權限
List<Privilige> Pris = privilegeServiceImpl.getAllPriviliges(nid);
return Pris;
}
}
這樣springMVC就能以json的形式來返回權限菜單數據,前臺的extjs就能解析到並加載。
實現的效果如下,當點擊父菜單時,會將節點id傳到後臺再從後臺加載數據回來。
注意從springMVC返回json數據時需要用到兩個jar包:
jackson-core-asl-1.9.13.jar和jackson-mapper-asl-1.9.13.jar