extjs 的权限问题 要求控制的对象是 菜单,按钮,URL


Posted in Javascript onMarch 09, 2010

解题思路1 : 重载Connection类
由于extjs和server端交互全都是 json格式的数据交互,server端不会控制页面的跳转,页面跳转,提示功能全都有extjs来完成。
extjs和server端的交互方法全都是继承自 Ext.data.Connection,这个类中可以拦截所有和server端交互的方法。
server端的权限控制用acegi做的,如果没通过acegi的验证,没有授权会返回到403.jsp,需要重登录会返回到 login.jsp。
因此重载Connection类,并改写其中的 handleResponse 方法,判断返回的结果是否是 403.jsp,login.jsp, 如果是就进行相应的控制,如果是正常的返回数据就继续向下执行。
我个人在403.jsp 和login.jsp 的第一行加上了 注释代码<!--权限控制自定义关键字-->,就是靠这个关键字来工作的
,代码如下:

//此处重载了Cunnection方法,用来拦截client与Server的交 互, 
//后台acegi拦截用户请求后,如果无权限,返回403.jsp;如果没登录,返回login.jsp; 
//通过Acegi拦截 后,才返回用户想要的Json结果 
Ext.override(Ext.data.Connection, { 
handleResponse : Ext.data.Connection.prototype.handleResponse.createInterceptor( 
function(response) { 
var resText=response.responseText; 
if (resText.length>10) { 
resText=resText.substr(0,9); 
} 
if (resText=='<!--login'){ 
window.top.location.href = topURL+"/login.jsp"; 
} else if (resText=='<!--deny-'){ 
if (resText=='<!--deny-'){ 
Ext.Msg.show({ 
title : '错误提示', 
msg : '禁止访问此功能,请和系统管理员联系', 
buttons : Ext.Msg.OK, 
icon : Ext.Msg.INFO 
}); 
}; 
} else if (resText=='<!--404--'){ 
Ext.Msg.show({ 
title : '错误提示', 
msg : '页面未找到', 
buttons : Ext.Msg.OK, 
icon : Ext.Msg.INFO 
}); 
} 
}) 
});

解题思路2: server端返回菜单json数据
我的菜单用tree来做的,在初始化主页面时先初始化菜单,
loader : new Ext.tree.TreeLoader({ 
dataUrl : 'getJsonMenus.do' 
}), 
这个'getJsonMenus.do'返回菜单json数据,在strut2中的配置为: 
<action name="getJsonMenus" class="jsonSystemAction" method="getJsonMenus"> 
<result type="json"> 
<param name="root">menus</param> 
</result> 
</action>

menus是个list<JsonMenu>,
JsonMenu的属性为:
private String text;
private boolean expanded;
private String id;
private boolean leaf;
private List<JsonMenu> children;
getJsonMenus.do 返回的格式是可以满足tree的格式要求的。
js代码如下
Ext.onReady(function() { 
setTimeout(function() { 
Ext.get('loading').remove(); 
Ext.getDom('header').style.visibility = 'visible'; 
var vp = new Ext.Viewport({ 
layout : 'border', 
defaults : { 
collapsible : true, 
split : true 
}, 
items : [{ 
xtype : 'box', 
region : 'north', 
applyTo : 'header', 
height : 30, 
split : false 
}, { 
title : currentUser, 
id : 'accordion-panel', 
layout : 'border', 
region : 'west', 
margins : '2 0 5 5', 
width : 200, 
minSize : 200, 
maxSize : 250, 
bodyStyle : 'background-color:#DFE8F6', 
defaults : { 
border : false 
}, 
bbar : [{ 
text : '开始', 
iconCls : 'icon-plugin', 
menu : new Ext.menu.Menu({ 
items : [{ 
text : '关于系统', 
iconCls : 'icon-info', 
handler : function() { 
new Ext.Window({ 
closeAction : 'close', 
resizable : false, 
bodyStyle : 'padding: 7', 
modal : true, 
title : '关于本系统', 
html : '本系统采用目前较为流行的技术实现,<br>前台使用了ExtJs技术,所以实现了跨浏览器<br>' + 
' 本程序在IE6,IE7,FireFox3均测试通过!<br><br>主要技术: Struts2 + Spring + iBatis + ExtJs<br><br>' 
+ '数  据  库: Oracle 9i', 
width : 300, 
height : 200 
}).show(); 
} 
}, { 
text : '退出系统', 
iconCls : 'icon-delete', 
handler : function() { 
Ext.Msg.confirm('操作提示', '您确定要退出本系统?', function(btn) { 
if ('yes' == btn) { 
Ext.Ajax.request({ 
url : 'logout.do', 
success : function() { 
location = '/'; 
}, 
failure : function() { 
Ext.Msg.show({ 
title : '错误提示', 
msg : '退出系统失败!', 
icon : Ext.Msg.ERROR, 
buttons : Ext.Msg.OK 
}); 
} 
}); 
} 
}); 
} 
}] 
}) 
}], 
items : [{ 
layout : 'accordion', 
region : 'center', 
items : [{ 
title : '导航菜单', 
iconCls : 'icon-nav', 
border : false, 
items : [{ 
xtype : 'treepanel', 
border : false, 
rootVisible : false, 
autoScroll : true, 
loader : new Ext.tree.TreeLoader({ 
dataUrl : 'getJsonMenus.do' 
}), 
root : new Ext.tree.AsyncTreeNode(), 
listeners : { 
'click' : function(n) { 
try { 
var sn = this.selModel.selNode || {}; 
if (n.leaf && n.id != sn.id) { 
Ext.getCmp('content-panel').layout.setActiveItem(n.id.substring(0, n.id 
.indexOf('-')) 
+ '-panel'); 
} 
} catch (e) { 
} 
} 
} 
}] 
},{ 
title : '系统设置', 
iconCls : 'icon-nav' 
}] 
}] 
}, { 
id : 'content-panel', 
region : 'center', 
layout : 'card', 
margins : '2 5 5 0', 
activeItem : 0, 
border : false, 
items : [start, p_company, p_user, p_dept, p_system, p_subject, p_category, p_resource] 
}] 
}); 
}, 250); 
});

这样就得到了菜单,还有网友提出了异步菜单解决方法,我也把它列到下面
解题思路3 : 同步加载所有的TAG,用hidden属性控制显示
所有的tag必须要同步加载后才可以控制component的hidden属性,异步加载不好用。
同步加载的方法如下:
//FUTURE_TAG全局的TAG控制类, 控制的组件的hidden属性,key=TAG的名字,value=true(组件隐藏),false(组件显示) 
var FUTURE_TAG={tbar1: false, tbar2: true}; 
var conn = Ext.lib.Ajax.getConnectionObject().conn; 
conn.open("GET", 'getJsonTags.do',false); 
conn.send(null); 
future_tag= eval('(' + conn.responseText + ')');

在js中TAG的用法如下:
var btn_add_system = new Ext.Button({ 
text : '添加', 
iconCls : 'icon-add', 
hidden: FUTURE_TAG.system_add, 
handler : function() { 
window_add_system.show(); 
} 
});

getJsonTags.do 返回一个Map对象,key是TAG名字,value是boolean
java的写法如下:
tagMap=new HashMap<String,Boolean>(); 
for (int i=0;i<allTagList.size();i++){ 
tagMap.put(allTagList.get(i).getResString(), true); 
}

strut2配置如下:
<action name="getJsonTags" class="jsonSystemAction" method="getJsonTags"> 
<result type="json"> 
<param name="root">tagMap</param> 
</result> 
</action>

这样就可以在后台控制前台的组件是否显示了,从而达到了我们的目的。
解决思路4:
通过ajax读取服务器端的权限值,返回这样的数据:
{tbar1: false, tbar2: true}
然后在extjs中:
var vResult = eval('(' + ajaxText + ')'); //得到{tbar1: false, tbar2: true}
这样就可以直接给tbar赋值了
disabled: vResult.tbar1
disabled: vResult.tbar2
解决思路5:
设置模块权限用于设置用户可以操作的权限。允许设置用户对模块的可操作与不可操作。
弹出设置权限子窗体
设置权限之前须选择一个用户。
Js代码
var row = grid_user.getSelectionModel().getSelected(); 
if(!row){ 
alert('对不起,您还未选择数据!'); 
return; 
} 
var row = grid_user.getSelectionModel().getSelected(); 
if(!row){ 
alert('对不起,您还未选择数据!'); 
return; 
}

创建一棵树,树放置在弹出窗体的中央。
Js代码
var root=new Ext.tree.TreeNode({ 
id:"root", 
text:"所有操作", 
checked:false, 
iconCls:'task-folder' 
}); 
var tree=new Ext.tree.TreePanel({ 
frame:false, 
region:'center', 
root:root, 
animate:true, 
enableDD:false, 
border:false, 
rootVisible:true, 
autoScroll:true 
}); 
var root=new Ext.tree.TreeNode({ 
id:"root", 
text:"所有操作", 
checked:false, 
iconCls:'task-folder' }); 
var tree=new Ext.tree.TreePanel({ 
frame:false, 
region:'center', 
root:root, 
animate:true, 
enableDD:false, 
border:false, 
rootVisible:true, 
autoScroll:true 
});

创建弹出子窗体。
Js代码
var win = new Ext.Window({ 
title:'设置模块权限', 
closable:true, 
width:300, 
height:500, 
plain:true, 
layout:'border', 
modal:true, 
items:[tree] 
}); 
win.show(this); 
var win = new Ext.Window({ 
title:'设置模块权限', 
closable:true, 
width:300, 
height:500, 
plain:true, 
layout:'border', 
modal:true, 
items:[tree] 
}); 
win.show(this);

在加载数据期间,给予提示。
Js代码
Ext.MessageBox.show({ 
title:'请稍候', 
msg:'正在加载数据,请耐心等待...', 
progress:true 
}); 
Ext.MessageBox.show({ 
title:'请稍候', 
msg:'正在加载数据,请耐心等待...', 
progress:true 
});

将根节点,所选择的用户行,父节点标志作为参数调用方法。
Js代码
getNodes(row,root,'root');
getNodes(row,root,'root');
从后台中取得数据并以树形式在客户端展现
方法定义与方法内容。
Js代码
function getNodes(row,root,parent){ 
//... 
} 
function getNodes(row,root,parent){ //...}

JSON 数据的定义。
Js代码
var record_pri = new Ext.data.Record.create([ 
{name:'modelId'}, 
{name:'modelName'}, 
{name:'sort'}, 
{name:'canUse'}, 
{name:'privilegeId'} 
]); 
var store_pri = new Ext.data.Store({ 
proxy: new Ext.data.HttpProxy({url:'../'}), 
reader: new Ext.data.JsonReader({root:'rows'},record_pri) 
}); 
var record_pri = new Ext.data.Record.create([ 
{name:'modelId'}, 
{name:'modelName'}, 
{name:'sort'}, 
{name:'canUse'}, 
{name:'privilegeId'} 
]); var store_pri = new Ext.data.Store({ 
proxy: new Ext.data.HttpProxy({url:'../'}), 
reader: new Ext.data.JsonReader({root:'rows'},record_pri) 
});

无刷新请求,获取数据并展现出来;并添加事件监听。当点击树某一节点时,判断是否已经从后台取得数据,如果还没有取则从后台获取数据,再根据返回的数据判断是叶子节点还是非叶子节点。然后以不同的方式展现与处理。
叶子节点和非叶子节点展现时,使用的图标不同。叶子节点没有添加单击事件,而非叶子节点添加了单击事件。
Js代码
Ext.Ajax.request({ 
url:'http://www.cnblogs.com/../privilegeAction.do?method=list', 
params:{ 
userId:row.get('userId'), 
parentId:parent 
}, 
success:function(response, request){ 
Ext.MessageBox.hide(); 
var res = Ext.util.JSON.decode(response.responseText); 
store_pri.loadData(res); 
for(var i=0;i<store_pri.getCount();i++){ 
var rec = store_pri.getAt(i); 
var canuse = (rec.get('canUse')=='是'?true:false); 
var modid = rec.get('privilegeId') + '-id-' + rec.get('modelId'); 
var node; 
if(rec.get('sort')=='菜单'){ 
node = new Ext.tree.TreeNode({ 
text:rec.get('modelName'), 
id:modid, 
checked:canuse, 
iconCls:'task-folder' 
}); 
node.on('click',function(node){ 
if(node.firstChild==null){ 
getNodes(row,node,get_mod_id(node.id)); 
} 
}); 
} else { 
node = new Ext.tree.TreeNode({ 
text:rec.get('modelName'), 
id:modid, 
checked:canuse, 
iconCls:'task' 
}); 
} 
node.on('checkchange',function(node,check){ 
Ext.Ajax.request({ 
url:'http://www.cnblogs.com/../privilegeAction.do?method=save2', 
params:{ 
privilegeId:get_rec_id(node.id), 
canuse:(check?'是':'否') 
}, 
success:function(response, request){ }, 
failure:function(){ 
Ext.MessageBox.hide(); 
alert('sorry!'); 
} 
}); 
}); 
root.appendChild(node); 
} 
root.expand(); 
}, 
failure:function(){ 
Ext.MessageBox.hide(); 
alert('sorry!'); 
} 
}); 
Ext.Ajax.request({ 
url:'http://www.cnblogs.com/../privilegeAction.do?method=list', 
params:{ 
userId:row.get('userId'), 
parentId:parent 
}, 
success:function(response, request){ 
Ext.MessageBox.hide(); 
var res = Ext.util.JSON.decode(response.responseText); 
store_pri.loadData(res); 
for(var i=0;i<store_pri.getCount();i++){ 
var rec = store_pri.getAt(i); 
var canuse = (rec.get('canUse')=='是'?true:false); 
var modid = rec.get('privilegeId') + '-id-' + rec.get('modelId'); 
var node; 
if(rec.get('sort')=='菜单'){ 
node = new Ext.tree.TreeNode({ 
text:rec.get('modelName'), 
id:modid, 
checked:canuse, 
iconCls:'task-folder' 
}); 
node.on('click',function(node){ 
if(node.firstChild==null){ 
getNodes(row,node,get_mod_id(node.id)); 
} 
}); 
} else { 
node = new Ext.tree.TreeNode({ 
text:rec.get('modelName'), 
id:modid, 
checked:canuse, 
iconCls:'task' 
}); 
} 
node.on('checkchange',function(node,check){ 
Ext.Ajax.request({ 
url:'https://3water.com/../privilegeAction.do?method=save2', 
params:{ 
privilegeId:get_rec_id(node.id), 
canuse:(check?'是':'否') 
}, 
success:function(response, request){ 
}, 
failure:function(){ 
Ext.MessageBox.hide(); 
alert('sorry!'); 
} 
}); 
}); 
root.appendChild(node); 
} 
root.expand(); 
}, 
failure:function(){ 
Ext.MessageBox.hide(); 
alert('sorry!'); 
} });

当非叶子节点被点击时,递归地调用方法来获取孩子节点。
获取行的ID和模块的ID。树的节点将行的ID和模块的ID一起取出来了。不然的话,如果只取得模块ID,而不取行ID,那么在修改的时候,则不能进行正确的修改。
Js代码
function get_rec_id(str){ 
var arr = str.split('-id-'); 
return arr[0]; 
} 
function get_mod_id(str){ 
var arr = str.split('-id-'); 
return arr[1]; 
}
Javascript 相关文章推荐
ie中js创建checkbox默认选中问题探讨
Oct 21 Javascript
利用js(jquery)操作Cookie的方法说明
Dec 19 Javascript
脚本合并提升javascript性能示例
Feb 24 Javascript
JavaScript使用二分查找算法在数组中查找数据的方法
Apr 07 Javascript
Function.prototype.apply()与Function.prototype.call()小结
Apr 27 Javascript
JS代码随机生成姓名、手机号、身份证号、银行卡号
Apr 27 Javascript
jQuery图片轮播(二)利用构造函数和原型创建对象以实现继承
Dec 06 Javascript
浅谈js闭包理解
Apr 01 Javascript
通过JQuery,JQueryUI和Jsplumb实现拖拽模块
Jun 18 jQuery
vue中根据时间戳判断对应的时间(今天 昨天 前天)
Dec 20 Javascript
JavaScript自定义超时API代码实例
Apr 30 Javascript
JS数组去重详情
Nov 07 Javascript
javascript 简单抽屉效果的实现代码
Mar 09 #Javascript
Javascript常考语句107条收集
Mar 09 #Javascript
风吟的小型JavaScirpt库 (FY.JS).
Mar 09 #Javascript
Jquery实现无刷新DropDownList联动实现代码
Mar 08 #Javascript
JavaScript this调用规则说明
Mar 08 #Javascript
javascript 放大镜 v1.0 基于Yui2 实现的放大镜效果
Mar 08 #Javascript
JavaScript中的闭包原理分析
Mar 08 #Javascript
You might like
php 批量替换程序的具体实现代码
2013/10/04 PHP
PHP统计二维数组元素个数的方法
2013/11/12 PHP
PHP中使用CURL获取页面title例子
2015/01/07 PHP
WordPress中用于更新伪静态规则的PHP代码实例讲解
2015/12/18 PHP
yii实现使用CUploadedFile上传文件的方法
2015/12/28 PHP
利用PHP生成静态html页面的原理
2016/09/30 PHP
Centos7 Yum安装PHP7.2流程教程详解
2019/07/02 PHP
Javascript倒计时代码
2010/08/12 Javascript
字符串的replace方法应用浅析
2011/12/06 Javascript
js实现网页标题栏闪烁提示效果实例分析
2014/11/20 Javascript
js实现四舍五入完全保留两位小数的方法
2016/08/02 Javascript
Google 地图叠加层实例讲解
2016/08/06 Javascript
jquery控制页面的展开和隐藏实现方法(推荐)
2016/10/15 Javascript
js实现图片左右滚动效果
2017/02/27 Javascript
超详细动手搭建一个VuePress 站点及开启PWA与自动部署的方法
2019/01/27 Javascript
浅谈Express.js解析Post数据类型的正确姿势
2019/05/30 Javascript
微信小程序sessionid不一致问题解决
2019/08/30 Javascript
javascript网页随机点名实现过程解析
2019/10/15 Javascript
[43:18]NB vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.22
2019/09/05 DOTA
跟老齐学Python之做一个小游戏
2014/09/28 Python
Python格式化css文件的方法
2015/03/10 Python
Python实现自定义顺序、排列写入数据到Excel的方法
2018/04/23 Python
python实时检测键盘输入函数的示例
2019/07/17 Python
通过 Python 和 OpenCV 实现目标数量监控
2020/01/05 Python
解决django中form表单设置action后无法回到原页面的问题
2020/03/13 Python
简单了解pytest测试框架setup和tearDown
2020/04/14 Python
Python图像读写方法对比
2020/11/16 Python
html5 迷宫游戏(碰撞检测)实例一
2013/07/25 HTML / CSS
MYPROTEIN澳大利亚官方网站:欧洲运动营养品牌
2019/06/26 全球购物
Shop Apotheke瑞士:您的健康与美容网上商店
2019/10/09 全球购物
客户代表实习人员自我鉴定
2013/09/27 职场文书
《莫泊桑拜师》教学反思
2014/04/23 职场文书
2014入党积极分子破除“四风”思想汇报
2014/09/14 职场文书
安全月宣传标语
2014/10/07 职场文书
写给消防战士们的一封慰问信
2019/10/07 职场文书
Python OpenCV之常用滤波器使用详解
2022/04/07 Python