1. 程式人生 > >extjs springMVC實現動態樹形選單

extjs springMVC實現動態樹形選單

最近由於專案需要,做一個樹形動態選單,用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包: