我用swing做了一个系统,也做好了相关角色权限的管控,但我不想在每个页面调用方法来判断用户所属的角色是否有操作权限,而是希望在用户登陆后便判断并控制。用户登陆后,出现一个新窗体,左边是Jtree,用户有访问某页面的权限时,该节点可有效点击,没有访问权限,该节点为灰色,点击无效。目前访问的权限我都控制好了,但增删改的权限就不好控制了,我期望的效果是如用户没有某页面的增加数据权限,则该页面执行添加的JButton按钮不显示,如有权限则显示,删除和修改也一样,有权限显示相关按钮,没有则不显示。如果在每个页面去判断的话,当然简单了,就是有权限,按钮设为setVisible(true),没有则为setVisible(false),但那样一来,我需要去修改很多页面,比较麻烦,所以,我分析,如果我将所有按钮名字统一化,例如所有页面执行添加的按钮名为Add,删除的就为Del,然后统一控制,这样就好办了,但如何去实现呢,有点无从下手了,请高手们指点,感激万分!

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【crl_lxy】截止到2008-07-17 09:11:48的历史汇总数据(不包括此帖):
    发帖的总数量:6                        发帖的总分数:170                      每贴平均分数:28                       
    回帖的总数量:237                      得分贴总数量:112                      回帖的得分率:47%                      
    结贴的总数量:6                        结贴的总分数:170                      
    无满意结贴数:0                        无满意结贴分:0                        
    未结的帖子数:0                        未结的总分数:0                        
    结贴的百分比:100.00%               结分的百分比:100.00%                  
    无满意结贴率:0.00  %               无满意结分率:0.00  %                  
    敬礼!
      

  2.   

    比如做這樣一個函數,參數是Buttons數組,數組中是你希望出現的按鈕種類(新增,刪除。)  然后做個循環,循環出數組中的值   用case或者別的基本就行了
    public void setButton(int[] Buttons){
    for(int i=0;i<Buttons.length;i++){
    switch(Buttons[i]){
    case。


    }
      

  3.   

    不知道这样行不行,继承jbutton,然后在里面设置可见性,用到jbutton的地方,全部换成那个子类
      

  4.   

    if (rp.CheckPrivilege(func_url,"A",userName))
    {
       this.btnAdd.setVisible(true);
    }
    else
    {
       this.btnAdd.setVisible(false);
    }
    我目前就是在每个页面去调用实现的,如果有权限就显示,目前还需要限制的权限有添加、删除和修改
      

  5.   

    其实你也可以把btn传进来,在相应的页面,用上这个函数不就可以了吗?
      

  6.   

    在登陆后,把所有按钮都初始化一遍,并且按照用户权限设置visible不过一般在公用的情况下才这么做
      

  7.   

    为什么不这样做呢:
    if(我是高级管理员){将所有的按钮都实现
    }else{只实现基本的按钮
    }
      

  8.   

    为什么不这样做呢:
    在登陆是判断
    if(我是高级管理员){将所有的按钮都实现
    }else{只实现基本的按钮
    }
      

  9.   

    用spring的拦截器不知是否可行。
      

  10.   

    首先分析下程序的执行顺序1.登陆,并获得权限
    2.通过权限产生窗口
    3.通过窗口进行操作那么我们可以在1-2之间做一个放值的操作这样,在产生窗口的时候,我们就可以通过已有的值去new窗口或者产生控件了。其他的话,也可以参照这个操作。
      

  11.   

    看来楼主昨天的答案还没有等到啊。。
    其实推荐下使用过滤器
    比如struts方面的过滤。。这样就不用你管控的很多。。
    当然。。我提供的只是思路啊
      

  12.   


    悟空,沒有不理你哈,呵呵用swing做的系統,呵呵
      

  13.   

    1. 先搜索到窗体内所有的按钮,如下:import java.util.List;
    import java.util.LinkedList;
    import java.awt.Frame;
    import java.awt.Component;
    import java.awt.Container;
    import javax.swing.JFrame;
    import javax.swing.JButton;/**
     * SwingUtil - Swing Tool Methods.
     * @author SageZk(张长弓)
     * @version 0.5
     */
    public class SwingUtil { private SwingUtil() { /*禁止创建此类的实例*/ } /**
     * 递归获取指定容器内的所有指定类型的组件。
     * @param con 要搜索的容器
     * @param cls 搜索的组件类型
     * @return 搜索到的组件列表
     */
    private static List<Component> getAllComponents(Container con, Class cls) {
    if (con == null || con.getComponentCount() == 0) return null;
    List<Component> coms = new LinkedList<Component>();
    List<Container> cons = new LinkedList<Container>();
    Component[] cs = con.getComponents();
    for (Component c : cs) {
    if (c.getClass() == cls) {
    coms.add(c);
    } else {
    cons.add((Container) c);
    }
    }
    for (Container c : cons) {
    List<Component> list = getAllComponents(c, cls);
    if (list != null) coms.addAll(list);
    }
    return coms;
    } /**
     * 获取指定的窗体内的所有指定类型的组件。
     * @param frm 要搜索的窗体
     * @param cls 搜索的组件类型
     * @return 搜索到的组件数组
     */
    public static Component[] getFrameComponents(Frame frm, Class cls) {
    if (frm == null || cls == null) throw new NullPointerException("frm or cls is null");
    Container root = frm;
    if (frm instanceof JFrame) root = ((JFrame)frm).getContentPane();
    List<Component> list = getAllComponents(root, cls);
    if (list == null) return new Component[0];
    return list.toArray(new Component[list.size()]);
    } //Unit Testing
    public static void main(String[] args) {
    TestFrame tf = new TestFrame();  //测试窗体
    tf.setVisible(true);
    Component[] cs = SwingUtil.getFrameComponents(tf, JButton.class);  //搜索所有 JButton
            for (int i = 0; i < cs.length;) {
             JButton btn = (JButton) cs[i++];
             String s = btn.getText();
             System.out.println(i + ". " + s);
            }
    }}2. 然后根据搜索到按钮的文本(通过 getText() 获取)或依据与按钮关联的动作监听器(通过 getActionListeners() 获取,这种方式更安全可维护性更强)来判断哪些按钮要被禁用(setEnabled(false))或隐藏(setVisible(false))。
      

  14.   

    采用工厂模式,封装new JButton(),然后在其中做判断
    而且便于以后的升级
      

  15.   

    你的意思是不是,在不同的页面都有不同的权限。而不同的权限会显示不同的操作权限。
    如果是的话。可以通过配置文件,或者数据库进行配置。例如,总共可以操作的控件有x个(控件可以不同种类),x从配置中进行读取。
    并从配置中读取一个 new boolean[1][x], 对组件的现实进行控制。控件的设计:
    假设有一组控件是button,则可以建一个继承button的新类button_p作为 父类,
    并抽象一个方法 init()
    {
    //setLabel(String label);
    //addActionListener(ActionListener l);
    //*************
    //*************
    }现在就可以继承这个父类生成两个子类button_add,button_del
    Jframe里面,建立一个button_p[x]数组。
    根据配置,
    如果有这个权限则 button_p[i] = (button_p) (Class.forName(name[i]).newInstance());---name[i],从配置中读取的类的名字。
    如果没有这个权限则 button_p[i] ==null,或者生成之后 setVisible(false);
    然后 if(button_p[i] !=null ) button_p[i].init();此时,即通过配置,进行了统一管理。如果要扩展新组件。
    此时想要增加一个关闭窗口的按钮。则只要新建一个子类button_close;
    并在配置中加入一行<button-name>button_close</button-name>;这时就可以把这个button_close权限赋予不同的用户。
      

  16.   

    如果你的系统用到了SQL,可以把你的组件信息放到数据库里去.比如一个表有ID(PK),ModuleID,Name,ClassName,ClassType,MessageFlag等字段,通过SQL做权限控制,你就可以达到按钮级授权.
    不同用户根据所处级别得到不同模块信息,再在所处模块中动态得到按钮或其它组件信息,进行动态创建比如得到了ClassType为JButton,ClassName为javax.swing.JButton,Name为新增;执行:
    if([ClassType].equals("JButton")){
        JButton button1 = (JButton)Class.forName([ClassName]);
        button1.setText([Name]);
        button1.set消息标志([MessageFlag]);
        button1.set某个属性([MessageFlag]);//属性是自己定的,用于传值到指定函数中.
        button1.addActionListener(xxx);
        xxx.add(button1);
        xxx.updateUI();
    }
    在你的Action触发函数中进行处理,比如
    JButton button = (JButton)event.getSource();
    if(button.get消息标志() == xxx){
        xxx.xxx(button.get某个属性1(),button.get某个属性2());
    }我说的这种方式比较灵活,可以做到按钮级授权,当然难度较大,前期考虑模块的结构要充分,否则修改不合理的结构很麻烦,在这里只是作为一种思路提供给你.
    以前我做过基于swing的进销存系统,就用的这种方式,前期花了很大的力气,把系统设计出来,相当还比较合理,到后期改起来很轻松.手都写痛了.......
      

  17.   


    34楼说的的确是个问题,但是这些按钮可以放在JToolBar上,就不会存在太多布局问题.
    我做系统那会布局管理器都重写了的,其他组件全是继承来的,比较灵活了,所以我觉得这个问题不会是问题,关键是你去怎么定义组件关系.
      

  18.   

    我的swing中的权限控制:这里的权限仅控制到菜单。
    1.db 中 有权限表,存放系统中所有的菜单模块名字。
    2.用户登录的时候从权限表中获取菜单名字,set可用
    3.show窗体。希望对LZ有点帮助
      

  19.   

    LZ做的是Web系统呢,还是桌面软件系统呢?
    怎么越搞越糊涂了,"而且这样还是需要去每个页面判断调用咧" >> 到底是页面还是窗体?
      

  20.   


     28楼 的代码完全被你无视了,都说了,用那个方法搜索到页面里所有的 JButton,然后根据用户的权限一个循环就能解决所有按钮的处理。
      

  21.   


    用swing做的呀,我在主貼里都有寫的
      

  22.   

    就是通過窗體左側的Jtree點擊訪問界面啊,我希望用戶在登錄后系統show出Jtree就統一控制整個系統的按鈕,遍歷用戶對系統中所有頁面所擁有的增刪查改權限,有權限則顯示相關按鈕,沒有權限則不顯示,而不是每個頁面去判斷調用
      

  23.   

    你左面用的是 JTree 右面是用 JDesktopPane 组织你的“页面”窗体的吗?
      

  24.   


    是的,右邊是JPane的界面
      

  25.   


    早说清楚问题早解决了,
    再不厌其烦地问一下,你右面是用的 JDesktopPane 组织一堆 JInternalFrame 来实现“页面”的,还是向 JPanel 里面加入了一堆对应于每一个“页面”的 JPanel 或其它组件来实现的?
      

  26.   

    我们的权限控制是这样做的.
    1.组件定义权值
    2.权值与管理员对应保存.(授权界面处理)
    4.管理员登陆时会获取其相应的权限
    3.继承swing基础组件,例JButton, JList,JComboBox等等,复写add(JComponent comp)方法,在这里判断其权值
    不符合的可以setEnabled(false);或不加载
      

  27.   

    暈了,界面都是分開的啦。。每個界面都是JPanel的
      

  28.   

    我更晕,那我刚才问你“右面是用 JDesktopPane 组织你的“页面”窗体的吗?”你说是!
      

  29.   

    如果如你所说:1. 操作流程:登录窗体(验证登录用户身份获取用户权限) -> 根据权限显示主窗体
    2. 主窗体布局为左右两栏,左面显示 JTree,右面根据 JTree 中选择的条目显示相应的 JPanel(里面有一堆按钮)来完成操作
    3. 右面那些 JPanel 是当选中 JTree 中条目时动态 new 出来的那解决方法如下:import java.util.List;
    import java.util.LinkedList;
    import java.awt.Component;
    import java.awt.Container;/**
     * SwingUtil - Swing Tool Methods.
     * @author SageZk(张长弓)
     * @version 0.6
     */
    public class SwingUtil {    private SwingUtil() { /*禁止创建此类的实例*/ }    /**
         * 递归获取指定容器内的所有指定类型的组件。
         * @param con 要搜索的容器
         * @param cls 搜索的组件类型
         * @return 搜索到的组件列表
         */
        private static List<Component> getAllComponents(Container con, Class cls) {
            if (con == null || con.getComponentCount() == 0) return null;
            List<Component> coms = new LinkedList<Component>();
            List<Container> cons = new LinkedList<Container>();
            Component[] cs = con.getComponents();
            for (Component c : cs) {
                if (c.getClass() == cls) {
                    coms.add(c);
                } else {
                    cons.add((Container) c);
                }
            }
            for (Container c : cons) {
                List<Component> list = getAllComponents(c, cls);
                if (list != null) coms.addAll(list);
            }
            return coms;
        }    /**
         * 获取指定的容器内的所有指定类型的组件。
         * @param con 要搜索的容器
         * @param cls 搜索的组件类型
         * @return 搜索到的组件数组
         */
        public static Component[] getFrameComponents(Container con, Class cls) {
            if (con == null || cls == null) throw new NullPointerException("con or cls is null");
            List<Component> list = getAllComponents(con, cls);
            if (list == null) return new Component[0];
            return list.toArray(new Component[list.size()]);
        }}1. 自己写个方法用于初始化 JPanel 页面,比如:
    public static JPanel initPage(JPanel page) {
        Component[] cs = getFrameComponents(page, JButton.class);  //搜索页面中所有 JButton
        for (int i = 0; i < cs.length; ++i) {
            JButton btn = (JButton) cs[i];
            //根据权限启用或禁用按钮
        }
        return page;
    }2. 在 JTree 条目选中事件处理代码中 new 页面时作初始化处理:
    JPanel page = initPage(new PageJPanel());  //PageJPanel 是你自己的页面类
      

  30.   

    謝謝65樓的朋友,那么,依你的意思,我是不是還需到每個頁面去調用JPanel initPage(JPanel page)?
      

  31.   


    你的 JTree 事件监听器应该只有一个吧,在那里调用就行。另外就算每个页面都调用一次也麻烦不到那儿去,你的每个页面不都得 new 吗,new 时外面包上一层 initPage(new ...) 就行了。
      

  32.   


    嗯,JTree的事件監聽都是以前的同事寫好了,JTree的節點都是從數據庫中讀出來的,同事寫的代碼邏輯好像有點復雜,也沒有注釋,挺暈的,找個時間我好好研究下你的方案我會試下,謝謝你!
      

  33.   

    可以提供一个Interface,该Interface中有一个函数CheckPrivilege判断是否有什么样的权限,然后各个Page实现该接口,在这个接口中根据权限进行处理。而你只要管理这些接口就可以了。