欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-17 18:41:09
解题思路1 : 重载connection类 由于extjs和server端交互全都是 json格式的数据交互,server端不会控制页面的跳转,页面跳转,提示功能全都有ex...

解题思路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:'//www.jb51.net/../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];
}