Extjs3.2+Json lib动态树与GridPanel简单展现

最近项目中要用到Extjs,网上搜了写文档看了之后,写了个小Demo。

Demo描述:

将部门信息用树展示出来,点击树节点的某个部门之后,弹出一个窗口,该窗口中展示这个部门中员工的列表。

首先,到http://www.sencha.com/products/js/download.php下载Extjs3.2的发布包,因为要用到json lib,所以还要到http://sourceforge.net/projects/json-lib/files/json-lib/下载json lib。

mysql数据库脚本:

DROP TABLE IF EXISTS `dept`; CREATE TABLE `dept` ( `deptno` int(11) NOT NULL AUTO_INCREMENT, `deptname` varchar(255) NOT NULL DEFAULT '', `parentno` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`deptno`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; LOCK TABLES `dept` WRITE; /*!40000 ALTER TABLE `dept` DISABLE KEYS */; INSERT INTO `dept` VALUES (1,'管理部',0); INSERT INTO `dept` VALUES (2,'销售部',0); INSERT INTO `dept` VALUES (3,'人力资源部',0); INSERT INTO `dept` VALUES (4,'开发部',0); INSERT INTO `dept` VALUES (5,'后勤部',0); INSERT INTO `dept` VALUES (6,'软件开发部',4); INSERT INTO `dept` VALUES (7,'增值开发部',4); INSERT INTO `dept` VALUES (8,'增值销售部',2); INSERT INTO `dept` VALUES (9,'产品销售部',2); INSERT INTO `dept` VALUES (10,'人妖部',3); /*!40000 ALTER TABLE `dept` ENABLE KEYS */; UNLOCK TABLES; DROP TABLE IF EXISTS `emp`; CREATE TABLE `emp` ( `empno` int(11) NOT NULL AUTO_INCREMENT, `empname` varchar(255) NOT NULL DEFAULT '', `gender` int(11) NOT NULL DEFAULT '0', `job` varchar(255) NOT NULL DEFAULT '', `deptno` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`empno`), KEY `fk_deptno` (`deptno`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; LOCK TABLES `emp` WRITE; INSERT INTO `emp` VALUES (1,'陈一',1,'staff boss',1); INSERT INTO `emp` VALUES (2,'黄二',1,'technical boss',1); INSERT INTO `emp` VALUES (3,'张三',0,'human resouce',3); INSERT INTO `emp` VALUES (4,'李四',1,'developer leader',6); INSERT INTO `emp` VALUES (5,'王五',1,'clerk',10); INSERT INTO `emp` VALUES (6,'赵六',1,'clerk',6); INSERT INTO `emp` VALUES (7,'钱七',1,'executor',6); INSERT INTO `emp` VALUES (8,'孙八',1,'super man',6); INSERT INTO `emp` VALUES (9,'方九',0,'oh, god',6); INSERT INTO `emp` VALUES (10,'无名氏',0,'无语',6); UNLOCK TABLES; ALTER TABLE `emp` ADD CONSTRAINT `fk_deptno` FOREIGN KEY (`deptno`) REFERENCES `dept` (`deptno`);

下面建立web工程:

分别新建DeptModel,EmpModel,TreeModel和PageModel

DeptModel.java:

public class DeptModel { private int deptno; private String deptname; private int parentno; ... }

EmpModel.java:

public class EmpModel { private Integer empno; private String empname; private String gender; private String job; private Integer deptno; ... }

TreeModel.java,用于生成部门树的模型:

public class TreeModel { private int id; private String text; private boolean leaf; private List<TreeModel> children = new ArrayList<TreeModel>(0); public TreeModel(){ } /** * 根据部门列表获取形如 [{id:"",text:"",leaf:,children:[]},{...},...]的JSON字符串 * @param models 部门列表List<DeptModel> * @return JSON格式的字符串,用于生成ext树 */ public String getJsonTreeModelString(List<DeptModel> models){ List<TreeModel> lst = new ArrayList<TreeModel>(0); for(DeptModel dm : models){ if(dm.getParentno()==0){ TreeModel root = new TreeModel(); root.setId(dm.getDeptno()); root.setText(dm.getDeptname()); List<TreeModel> children = getChildren(models,root); //递归获取子集 if(children.size()>0){ root.setLeaf(false); root.setChildren(children); }else{ root.setLeaf(true); root.setChildren(new ArrayList<TreeModel>(0)); } lst.add(root); } } JsonConfig config = new JsonConfig(); config.setExcludes(new String[]{"models"}); config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT); return JSONArray.fromObject(lst,config).toString(); } /** * 递归获取节点的子集的方法 * @param models 部门列表 * @param parentModel 根节点,即deptno=0的根节点部门 * @return List<TreeModel> 树模型列表 */ public List<TreeModel> getChildren(List<DeptModel> models,TreeModel parentModel){ List<TreeModel> lst = new ArrayList<TreeModel>(0); for(DeptModel dm : models){ if(parentModel.getId() == dm.getParentno()){ TreeModel tm = new TreeModel(); tm.setId(dm.getDeptno()); tm.setText(dm.getDeptname()); List<TreeModel> children = getChildren(models,tm); if(children.size()>0){ tm.setLeaf(false); tm.setChildren(children); }else{ tm.setLeaf(true); tm.setChildren(new ArrayList<TreeModel>(0)); } lst.add(tm); } } return lst; } //省略getter,setter方法... }

PageModel.java,用于分页的模型:

public class PageModel { private int total; private List lst; ... }

下面添加工程对Extjs3.2的支持:

解压ext-3.2.0.zip到某个路径,复制adapter、pkgs、resource文件夹、ext-3.2.0/src/locale/ext-lang-zh_CN.js和ext-3.2.0/ext-all.js到WebRoot/js下面,这样就完成了对Extjs功能的支持。

接下来完成从数据库获取部门信息和人员信息并转换成JSON格式:

deptProcessor.jsp:

<%@ page language="java" pageEncoding="UTF-8"%> <%@ page import="com.model.TreeModel" %> <%@ page import="com.model.DeptModel" %> <%@ page import="java.sql.*,java.util.*" %> <% Class.forName("com.mysql.jdbc.Driver"); java.sql.Connection conn = java.sql.DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root"); PreparedStatement pstmt = conn.prepareStatement("select * from dept"); ResultSet rs = pstmt.executeQuery(); List<DeptModel> models = new ArrayList<DeptModel>(); while(rs.next()){ DeptModel model = new DeptModel(); model.setDeptno(rs.getInt("deptno")); model.setDeptname(rs.getString("deptname")); model.setParentno(rs.getInt("parentno")); models.add(model); } String jsonTreeModelString = new TreeModel().getJsonTreeModelString(models); out.println(jsonTreeModelString); %>

empProcessor.jsp:

<%@ page language="java" pageEncoding="UTF-8"%> <%@ page import="com.model.EmpModel" %> <%@ page import="com.model.PageModel" %> <%@ page import="net.sf.json.JSONObject" %> <%@ page import="java.sql.*,java.util.*" %> <% Integer deptno = -1; Integer start = 0; Integer limit = 0; if(request.getParameter("deptno") != null){ deptno = Integer.parseInt(request.getParameter("deptno").toString()); } if(request.getParameter("start") != null){ start = Integer.parseInt(request.getParameter("start").toString()); } if(request.getParameter("limit") != null){ limit = Integer.parseInt(request.getParameter("limit").toString()); } Class.forName("com.mysql.jdbc.Driver"); java.sql.Connection conn = java.sql.DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root"); PreparedStatement pstmt = conn.prepareStatement("select * from emp where deptno=? limit ? ,?"); pstmt.setInt(1,deptno); pstmt.setInt(2,start); pstmt.setInt(3,limit); ResultSet rs = pstmt.executeQuery(); List<EmpModel> models = new ArrayList<EmpModel>(); while(rs.next()){ EmpModel model = new EmpModel(); model.setEmpno(rs.getInt("empno")); model.setEmpname(rs.getString("empname")); model.setGender(rs.getInt("gender")==1?"男":"女"); model.setJob(rs.getString("job")); model.setDeptno(rs.getInt("deptno")); models.add(model); } pstmt = conn.prepareStatement("select count(*) from emp where deptno=?"); pstmt.setInt(1,deptno); rs = pstmt.executeQuery(); int total = 0; if(rs.next()){ total = rs.getInt(1); } PageModel pageModel = new PageModel(); pageModel.setTotal(total); pageModel.setLst(models); String jsonEmpModelString = JSONObject.fromObject(pageModel).toString(); out.println(jsonEmpModelString); %>

最后列用Extjs提供的TreePanel和Window,GridPanel分别显示部门和人员信息:

tree.jsp:

<%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Extjs Tree Demo</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link rel="stylesheet" type="text/css" href="js/extjs/resources/css/ext-all.css" mce_href="js/extjs/resources/css/ext-all.css" /> <mce:script src="js/extjs/adapter/ext/ext-base.js" mce_src="js/extjs/adapter/ext/ext-base.js"></mce:script> <mce:script src="js/extjs/ext-all.js" mce_src="js/extjs/ext-all.js"></mce:script> <mce:script src="js/extjs/ext-lang-zh_CN.js" mce_src="js/extjs/ext-lang-zh_CN.js"></mce:script> <mce:script type="text/javascript"><!-- Ext.onReady(function(){ //生成部门树结构 var treeLoader = new Ext.tree.TreeLoader({ dataUrl:"deptProcessor.jsp" }); var rootNode = new Ext.tree.AsyncTreeNode({ text: '所有部门' }); var tree = new Ext.tree.TreePanel({ renderTo:'treecontainer', loader: treeLoader, root: rootNode, width:200, height:300, listeners:{ click:showEmps } }); tree.expandAll(); }); //点击部门节点后的事件处理 function showEmps(n){ var deptno = n.attributes.id; var deptname = n.attributes.text; var win = new Ext.Window({ title:deptname, width:500, height:300 }); var dataProxy = new Ext.data.HttpProxy({ url:"empProcessor.jsp?deptno="+deptno }); var reader = new Ext.data.JsonReader({totalProperty:"total",root:"lst"},[ "empno","empname","gender","job","deptno" ]); var store = new Ext.data.Store({ proxy:dataProxy, reader:reader }); store.load({params:{start:0,limit:5}}); var columnModel = new Ext.grid.ColumnModel([ {header:"编号",width:100,dataIndex:"empno"}, {header:"姓名",width:120,dataIndex:"empname"}, {header:"性别",width:100,dataIndex:"gender"}, {header:"职位",width:100,dataIndex:"job"} ]); //分页 var pageBar = new Ext.PagingToolbar({ store:store, pageSize:5, displayInfo:true, displayMsg:"当前为{0}-{1}条,共{2}条", emptyMsg:"没有记录" }); var gridPanel = new Ext.grid.GridPanel({ width:480, autoHeight:true, cm:columnModel, store:store, bbar:pageBar }); win.add(gridPanel); win.show(Ext.getBody()); } // --></mce:script> </head> <body style="padding:30px 20px" mce_style="padding:30px 20px"> <div id="treecontainer" style="height:300px; width:200px;"></div> </body> </html>

在浏览器中输入 http://127.0.0.1:8080/Extjs/tree.jsp测试,效果如下:Extjs3.2+Json lib动态树与GridPanel简单展现

<!--StartFragment -->
哈哈,很简单吧。。。