EasyUI+springmvc +spring +hibernate整合一起实现权限控制,项目名'sshwebtest'2

EasyUI前端应用基础续编。

datagrid网格之模糊查询与数据表冻结

模糊查询:
这里以学生姓名stuname作模糊查询,where 1=1 and stuname='%xxx%' 注:1=1表示所有。
以上例为基础:div作为table的一个工具,div里有两个输入框,一个链接按钮,分别用于用户输入学生名,与学号作对学生的模糊查询。
一。jsp

            
学生ID:
学生姓名:
搜索

二。js 注意:url:''/sshwebtest/getAllPagerStudents'这是链接到后台的控制层'

 $(function(){
           $("#dg").datagrid({
               title:"用户信息表",
               //url:"/sshwebtest/getAllStudentsD",    //没有分页显示的远程后台数据处理
               url:"/sshwebtest/getAllPagerStudents",
               pagination:true,  //分页显示,有修改每页显示多少条功能,不用写代码
               pageSize:5,       //初始化每页显示几条记录
               pageList:[5,10,25,30,100],                //设置分页每页能显示多少条记录选择项,这里是每页有5条,10条,,,多个选项,
              // method:"post",                           //默认为post可以不写这行代码
               columns:[[
                   {field:"ck",checkbox:"true"},          //最左侧有复选框,可供我们选择,
                   {field:"id",title:"id",width:100},
                   {field:"stuname",title:"stuname",width:100},
                   {field:"password",title:"password",width:100},
                   {field:"state",title:"state",width:100,formatter:function(value,row,index){
                                                                        if(value == 1){
                                                                            return "正常";
                                                                        }else{
                                                                            return "禁用状态";
                                                                        }
                                                                        
                       
                   }},
                   {field:"regDate",title:"regDate",width:100},
                   {field:"height",title:"height",width:100}
               ]],            //两个中括号,表示二维表格
               striped:true,    //把表格网纹化,即奇偶行不同背影 色
               toolbar:"#tb",
               toolbar:[                    //网格上有工具栏,有一个工具(铅笔)
                   {
                      text:"编辑",
                       iconCls:"icon-edit",
                       handler:function(){
                           //alert("单击");
                             var datas = $("#dg").datagrid("getChecked");   //获取选中复选框中记录
                             if(datas.length > 0 ){
                                 for(var i=0;i

三.后台控制层StuCtroller.java与service,dao的一个代码片段

//带分页显示所有学生信息,学生姓名作模糊查询,不用注入对象,这里我们直接用网页与easyui交互,用到json格式数据,所以用@ResponseBody注解
@Controller
public class StuController {
    @Autowired
    private StudentService stuService;
    @ResponseBody
    @RequestMapping(value="/getAllPagerStudents",method=RequestMethod.POST)
    public Pager getAllPagerStudents(Integer page,
                                              Integer rows,  //page,rows值由easyui 网格自动发送的请求而过来的
                                              @RequestParam(value="id",required=false) Integer id,
                                              @RequestParam(value="stuname",required=false) String stuname)    //id,stuname是接收输入框输入的数据
      {    
        System.out.println("StuController.java中由easyui 网格发送的page,rows   "+page+","+rows);
        if(page != null && page>0) SystemContext.setPageSize(rows);            //每一页两条记录
        if(rows !=null && rows>0) SystemContext.setPageOffset((page-1)*rows);  //从第一条记录开始分
        Student stu = new Student();
        if(id!=null && id >0 ) stu.setId(id);
        if(stuname !=null && !"".equals(stuname) ) stu.setStuname(stuname);
        Pager pager = stuService.getAllPagerStus(stu);
        SystemContext.removePageOffset();
        SystemContext.removePageSize();
        return pager;
        
    }
}
-----------------------------------------------------StudentServiceImpl--------------------------------------------
@Service("stuService")
public class StudentServiceImpl extends BaseServiceIpml implements StudentService {
@Override
    public Pager getAllPagerStus(Student stu) {
        return stuDao.getAllPagerStus(stu);
    }
   }
------------------------------------------------------StudentService---------------------------------------
public interface StudentService extends BaseService {
    /**
     * 获取所有学生信息,不支持分页
     * @return
     */
    public List getAllStus();
    /**
     * 获取所有学生信息,支持分页
     * @param stu 
     * @return
     */
    public Pager getAllPagerStus(Student stu);
}
-----------------------------------------------------------StudentDaoImpl.java------------------------------
@Repository("stuDao")
public class StudentDaoImpl extends BaseDaoImpl implements StudentDao{
    //下面写的方法都是本类个性化的方法
    @Override
    public List getAllStus() {
        String hql="from Student";
        return super.list(hql, null, null);
    }
       //分页且模糊查询
    @Override
    public Pager getAllPagerStus(Student stu) {
        String hql="from Student s where 1=1";
        if(stu.getId()>0) hql+=" and u.id="+stu.getId();
        if(stu.getStuname()!=null &&!"".equals(stu.getStuname()))
            hql+=" and s.stuname like'%"+stu.getStuname()+"%'";
        return super.find(hql, null, null);
    }
      
}
--------------------StudentDao.java-------------------------------------
public interface StudentDao extends BaseDao{
   /**
    * 获取所有学生信息,不支持分页
    */
    public List getAllStus();
    /**
     * 获取所有学生信息,支持分页
     * @param stu 
     * @return
     */
    public Pager getAllPagerStus(Student stu);
}
---------------------------------------------Pager.java--------------------------------------------------------
public class Pager {
    /**
     * 分页的大小,每页显示数据的条数
     */
    private int size;
    // 每页的第一条数据的,条数索引
    private int offset;
    /**
     * 查询出来的总的数据条数,rows--与easyui分页插件里变量名称一致
     */
    private long total;
    /**
     * 每张每页是具体数据(一页所有的记录),rows--easyui与分页插件里变量名称一致
     */
    private List rows;

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getOffset() {
        return offset;
    }

    public void setOffset(int offset) {
        this.offset = offset;
    }

    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
    }

    public List getRows() {
        return rows;
    }

    public void setRows(List rows) {
        this.rows = rows;
    }

    @Override
    public String toString() {
        return "Pager [size=" + size + ", offset=" + offset + ", total=" + total + ", rows=" + rows + "]";
    }

}
-------------------SystemContext.java--------------------------------
/**
 * ThreadLocal:数据共享,本地线程变量里的数据,每个线程中创建副本,在多条线程中,给这个变量赋值,
 * 每条线程使用不会冲突 进行分页信息通信
 * 排序信息通信
 * 
 * @author Administrator
 *
 */
public class SystemContext {
    // 分页大小,每页显示的数据条数
    private static ThreadLocal pageSize = new ThreadLocal<>();
    // 每页的起始的条数索引
    private static ThreadLocal pageOffset = new ThreadLocal<>();
    // 排序的字段
    private static ThreadLocal sort = new ThreadLocal<>();
    // 排序方式
    private static ThreadLocal order = new ThreadLocal<>();

    public static Integer getPageSize() {
        return pageSize.get();
    }

    public static void setPageSize(Integer _pageSize) {
        pageSize.set(_pageSize);
    }

    public static Integer getPageOffset() {
        return pageOffset.get();
    }

    public static void setPageOffset(Integer _pageOffset) {
        pageOffset.set(_pageOffset);
    }

    public static String getSort() {
        return sort.get();
    }

    public static void setSort(String _sort) {
        sort.set(_sort);
    }

    public static String getOrder() {
        return order.get();
    }

    public static void setOrder(String _order) {
        order.set(_order);
    }

    public static void removePageSize() {
        pageSize.remove();
    }

    public static void removePageOffset() {
        pageOffset.remove();
    }

    public static void removeSort() {
        sort.remove();
    }
    
    public static void removeOrder() {
        order.remove();
    }

}
------------------------------------------------------------------------BaseService.java--------------------
public interface BaseService {
// 添加
       public T add(T t);
        // 删除
        public void delete(int id);
         // 修改
    public void update(T t);
         // 查询
    public T load(int id);
}
----------------------------------------------------------BaseServiceImpl.java-------------------------------
public class BaseServiceIpml implements BaseService {
    
    @Autowired
    protected BaseDao baseDao;

    @Override
    public T add(T t) {
        return baseDao.add(t);
    }

    @Override
    public void delete(int id) {
        baseDao.delete(id);
    }

    @Override
    public void update(T t) {
        baseDao.update(t);
    }

    @Override
    public T load(int id) {
        return baseDao.load(id);
    }

}
------------------------------------------------------------BaseDao.java接口--------------------------------
public interface BaseDao {
    // 添加
       public T add(T t);
        // 删除
        public void delete(int id);
         // 修改
    public void update(T t);
         // 查询
    public T load(int id);

}
-----------------------------------------------------------BaseDaoImpl.java------------------------------
/**
 * BaseDaoImpl:操作数据库的基本方法代码
 * 
 * @author Administrator
 * @param 
 */
public class BaseDaoImpl implements BaseDao {

    @Autowired
    private SessionFactory sessionFactory;  //spring.xml配置了

    private Class clazz;

    public Class getClazz() {
        /*
        Type type= this.getClass().getGenericSuperclass();//this将代表BaseDaoImpl的子类对象如:UserDaoImpl extends BaseDaoImpl
        ParameterizedType pt=(ParameterizedType) type;
        Type[] types = pt.getActualTypeArguments();
        Class clz = (Class) types[0];
        return clz;
        */
        if (clazz == null) {
            clazz = ((Class) ((((ParameterizedType) (this.getClass().getGenericSuperclass()))
                    .getActualTypeArguments())[0]));
        }
        return clazz;

    }

    /**
     * 获取数据连接回话的方法
     */
    public Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public T add(T t) {
        getSession().save(t);
        return t;
    }

    @Override
    public void delete(int id) {
        getSession().delete(load(id));
    }

    @Override
    public void update(T t) {
        getSession().update(t);
    }

    @SuppressWarnings("unchecked")
    @Override
    public T load(int id) {
        return (T) getSession().load(getClazz(), id);//hibernate中有load(xxx.class,xxx)方法加载数据库数据即返回记录
    }

    /**
     * 用hql语句查询多条记录,没有分页,list返回对象.两种spring处理数据库的占位符
     * @param hql
     * @param objs  替换hql语句中?占位符的实参
     * @param alias   替换hql语句中:name占位符的实参
     * @return
     */
    //其它类如UserDaoImpl,StudentDaoImpl等调用如 :return super.list(hql, null, null);
    
    @SuppressWarnings("unchecked")
    public List list(String hql, Object[] objs, Map alias) {
        hql = initSort(hql);      //初始化排序规则
        Query query = getSession().createQuery(hql);
        setParameter(query,objs);  //将hql里?占位符替换
        setAliasParameter(query,alias);
        return query.list();
    }

    /**
     *  替换hql语句中:name占位符的实参
     * @param query
     * @param alias
     */
    @SuppressWarnings("rawtypes")
    private void setAliasParameter(Query query, Map alias) {
        if(alias != null) {
            Set keys = alias.keySet();
            for(String key:keys) {
                Object val = alias.get(key);         //取key对应的值
                if(val instanceof Collection) {       //判断是不是一个集合
                    query.setParameterList(key, (Collection)val);
                }else {
                    query.setParameter(key, val);
                }
            }
        }
    }

    /**
     * 将hql里?占位符替换
     * @param query
     * @param objs
     */
    private void setParameter(Query query,Object[] objs) {
        if(objs != null && objs.length > 0) {
            int index = 0;
            for(Object obj:objs) {
                query.setParameter(index++, obj);
            }
        }
    }

    /**
     * 给hql语句加排序规则
     * @param hql
     * @return
     */
    private String initSort(String hql) {
        String sort = SystemContext.getSort(); // 数据我们可以在Controller放
        String order = SystemContext.getOrder();
        if (sort != null && !"".equals(sort.trim())) {
            hql += " order by " + sort;   //例:String hql="select from User order by desc...."
            if (!"desc".equals(order)) {
                hql += " asc";
            } else {
                hql += " desc";
            }
        }
        return hql;
    }
    
    /**
     * 查询多条数据,支持分页
     * @param hql
     * @param objs
     * @param alias
     * @return
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public Pager find(String hql, Object[] objs, Map alias){
        hql = initSort(hql);//初始化排序规则
        Query query = getSession().createQuery(hql);
        setParameter(query,objs);//将hql里?占位符替换
        setAliasParameter(query,alias);
        Pager pager = new Pager<>();
        setPager(query,pager);
        List datas = query.list();
        pager.setRows(datas);
        
        //还需要一个查询的中条数   select count(*) from  users where id>10
        String countHql = getCountHql(hql);
        Query countQuery = getSession().createQuery(countHql);
        setParameter(countQuery,objs);//将hql里?占位符替换
        setAliasParameter(countQuery,alias);
        long total = (long) countQuery.uniqueResult();
        pager.setTotal(total);
        
        return pager;
        
    }

    private String getCountHql(String hql) {
        String hhql = hql.substring(hql.indexOf("from")); // 拿到hql语句的form开始后半部分:from  users where id>10
        String countHql = "select count(*) " + hhql;
        //hql语句,fetch
        countHql = countHql.replace("fetch", "");
        return countHql;
    }

    private void setPager(Query query, Pager pager) {
        Integer pageSize = SystemContext.getPageSize();
        Integer pageOffset = SystemContext.getPageOffset();
        if(pageOffset == null || pageOffset < 0) {
            pageOffset = 0; // pageOffset的默认值
        }
        if (pageSize == null || pageSize < 0) {
            pageSize = 10;  // 没有设置每页大小,默认每页显示10条
        }
        pager.setOffset(pageOffset);
        pager.setSize(pageSize);
        // data数据,也就是分页的数据  select id,username,pasword from  users where id>10; 一张页面上显示的数据
        query.setFirstResult(pageOffset).setMaxResults(pageSize);
        
    }
    
    //使用sql语句查询的方法,list,pager
    
    /**
     * 针对一些特殊的查询,返回不受泛型的制约,返回object
     * @param hql
     * @param objs
     * @param alias
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Object queryByHql(String hql, Object[] objs, Map alias) {
        Query query = getSession().createQuery(hql);
        setParameter(query,objs);//将hql里?占位符替换
        setAliasParameter(query,alias);
        return query.uniqueResult();
    }
    
    /**
     * 应对某些特殊情况要用hql语句,来做更新
     * @param hql
     * @param objs
     * @param alias
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void updateByHql(String hql, Object[] objs, Map alias) {
        Query query = getSession().createQuery(hql);
        setParameter(query,objs);//将hql里?占位符替换
        setAliasParameter(query,alias);
        query.executeUpdate();
    }

}

四,DAO层,service层见代码 'sshwebtest'项目
五,测试
http://localhost/sshwebtest/

image.png

数据表冻结
项目中,显示的数据字段数很多,屏幕宽显示不小,这时,就会生成滚动条进行滚动查看:有些列和行,我们不希望它随着滚动而被遮盖,这个时候我们就可以使用冻结功能:
1.冻结列:

frozenColumns      array        和列( column )属性一样,但是这些列将被冻结在左边

应用格式:frozenColumns:[[]]
例:冻结第一到第三列:id,password,stuname

 $("#dg").datagrid({
               width:500,       //网格的宽,设置小一点可以看出移动滚动条的效果
               height:300,
               title:"用户信息表",
               //url:"/sshwebtest/getAllStudentsD",    //没有分页显示的远程后台数据处理
               url:"/sshwebtest/getAllPagerStudents",
               pagination:true,  //分页显示,有修改每页显示多少条功能,不用写代码
               pageSize:5,       //初始化每页显示几条记录
               pageList:[5,10,25,30,100],                //设置分页每页能显示多少条记录选择项,这里是每页有5条,10条,,,多个选项,
               frozenColumns:[[
                   {field:"ck",checkbox:"true"},          //最左侧有复选框,可供我们选择,
                   {field:"id",title:"id",width:100},
                   {field:"stuname",title:"stuname",width:100},
                   {field:"password",title:"password",width:100},
               ]],
               columns:[[                //列数组
                      {field:"state",title:"state",width:100,formatter:function(value,row,index){
                                                                        if(value == 1){
                                                                            return "正常";
                                                                        }else{
                                                                            return "禁用状态";
                                                                        }
                                                                        
                       
                   }},
                   {field:"regDate",title:"regDate",width:100},
                   {field:"height",title:"height",width:100}
               ]],            //两个中括号,表示二维表格
               striped:true,
…………………………其它代码与上面一样

image.png

2.冻结行:
当数据行很多时,会呈现垂直的滚动条,但是向下滚动,表头却被淹没了,这不符
合人类偷懒的特点(我怎么可能记得住每列的数据代表的意思!),所以需要固定表头。
21.fit: true, // 单独 fit 固定表头,
注:固定了表头,只显示第一页,显分页栏不见了,冻结的列也失效
22.onLoadSuccess: function(){
$(this).datagrid("freezeRow",0); // 额外固定某些行
}

--------
onLoadSuccess: function(){
                   $(this).datagrid("freezeRow",0); // 额外固定某些行(0表示第一行)
                 },
               frozenColumns:[[
                   {field:"ck",checkbox:"true"},          //最左侧有复选框,可供我们选择,
                   {field:"id",title:"id",width:100},
                   {field:"stuname",title:"stuname",width:100},
                   {field:"password",title:"password",width:100},
               ]],
               //fit:true,
               columns:[[                //列数组
                      {field:"state",title:"state",width:100,formatter:function(value,row,index){
                                                                        if(value == 1){
                                                                            return "正常";
                                                                        }else{
                                                                            return "禁用状态";
                                                                        }
                                                                        
                       
                   }},
                   {field:"regDate",title:"regDate",width:100},
                   {field:"height",title:"height",width:100}
               ]],      
-----------------

网格可编辑保存数据到数据库中。

  1. 大概功能代码editor:点击一行,显示可编辑框,上一次点的行处于不可编辑状态
------
columns:[[                //列数组
                   {field:"ck",checkbox:"true"},          //最左侧有复选框,可供我们选择,
                   {field:"id",title:"id",width:100},
                   {field:"stuname",title:"stuname",width:100,editor:{type:"textbox"}},
                   {field:"password",title:"password",width:100},
                      {field:"state",title:"state",width:100,formatter:function(value,row,index){
                                                                        if(value == 1){
                                                                            return "正常";
                                                                        }else{
                                                                            return "禁用状态";
                                                                        }
                                                                        
                       
                   },editor:{type:"textbox"}},
                   {field:"regDate",title:"regDate",width:100,editor:{type:"datebox"}},
                   {field:"height",title:"height",width:100,editor:{type:"numberbox",options:{precision:2}}},//precision 编辑后保留两位小数
                   {field:"roles",title:"roles",width:100,formatter:function(value,row,index)
                     {
                          //这里只是举例讲,只列一个角色权根
                        var roleNameStr="";  
                        console.log(value);   //[{0...}] [{0...}] [{0...}]从浏览器控制台F12中可以看出value是一个二维数组,而记录都存在第二维的0下标上的一维数组中
                        if(value !=null && value.length >0) 
                            roleNameStr = value[0].roleName;
                        return roleNameStr;
                      },editor:{type:"combobox",options:{url:"/sshwebtest/getRoles",method:"post",valueField:"id",textField:"roleName",required:true,panelHeight:160} 
                   }}
               ]],            //两个中括号,表示二维表格
               onClickRow:function(index){           //可编辑行单击事件,此处用于打开可编辑网格功能.index为点击的行索引
                   if(editIndex !=index){  //默认情况下,点击某一行,它可编辑,但是我们再点一行时,上一点击行仍处于可编辑,这可不好,
                       $("#dg").datagrid("rejectChanges")
                   }
                   $("#dg").datagrid("beginEdit",index);
                    $("#dg").datagrid("selectRow",index);       //选中某一行后,左则的复选框打上勾
                    editIndex = index;
               },
  });
var editIndex;
image.png
  1. 编辑后保存到数据库,取消编辑。
    1.jsp中添加两个链接按钮 在html中表示空格。
 保存  取消 。。。。。。。

2.js中添加两个链接按钮的单击事件

//保存修改的记录
           $("#save_stu").click(function(){
               //添加到数据库之前,数据有效性检验
               //根据editIndex拿到这个row对象
               var row = $("#dg").datagrid("getRows")[editIndex];
               //根据editIndex,拿到行的编辑器,简单类型的字段,直接获取值,roles是Role对象类型,单独处理
               var editor = $("#dg").datagrid("getEditor",{index:editIndex,field:"roles"});
               var roleid = $(editor.target).combobox("getValue");  //获取角色的编号
               var roletext = $(editor.target).combobox("getText"); //获取角色的描述文本
               //让datagrid接受修改,并通ajax发出修改请求
               $("#dg").datagrid("acceptChanges");
               $.ajax({
                   url:"/sshwebtest/updateStudent",
                   method:"post", 
                   //如果说Student对象简单,属性没有复杂的关联性,但我们Student中有set集合role对象,springmvc不能解析,所以必须声明请求的数据类型为json数据格式
                   contentType:"application/json;charset=utf-8",
                   //传过去的数据格式,从js的对象格式转化为json格式,stringif()可以将java对象转化为json
                   data:JSON.stringify({     //以下字段名要与Student对象的成员变量名相同
                       id:row.id,
                       stuname:row.stuname,
                       password:row.password,
                       state:row.state,
                       regDate:row.regDate,
                       height:row.height,
                       roles:[{id:roleid,roleName:roletext}]    //[]表示集合
                       
                   }),
                   success:function(rs){  //如呆请求成功,会发回来一个对象rs(rs随便起名,但一定要写在小括号中)
                       if(rs == "success"){
                           editIndex = undefined;
                           $("#dg").datagrid("reload");
                       }else{
                           alert("修改失败!");
                       }
                   }
               
               })
               
           });
 //取消编辑,很简单,只要上的面拒绝修改代码即可
           $("#undo_stu").click(function(){
               $("#dg").datagrid("rejectChanges");
               editIndex = undefined;
  })

3.后台响应前台的$.ajx()请求 StuController.java
基Role.java,RoleDao.java RoleDaoImpl.java,RoleService.java,RoleServiceImpl.java见项目 'sshwebtest'

@ResponseBody     //返回json格式到网页中  
    @RequestMapping(value="/updateStudent", method=RequestMethod.POST)
    public String updateStudent(@RequestBody Student stu) {   //把接收的参数转为json格式数据
        stuService.update(stu);
        return "success";
        
    }

4.测试:
首先:给表sb_roles写入几个记录,如1-超级管理员 2-一般管理员……。
sb_student_role写入几个记录 1 1,2 1, 即每个学生对应自已的权限
其次:http://localhost/sshwebtest 回车,

image.png

基于权限控制模型实现学生/用户角色与权设置

1权限控制模型

----我们在做任何一款产品的时候,或多或少都会涉及到用户和权限的问题。譬如,做企业类软件,不同部门、不同职位的人的权限是不同的;做论坛类产品的时候,版主和访客权限也是不一样的;再例如一款产品的收费用户和免费用户权限也是迥然不同的。
----我们去参照已有的比较成熟的权限模型:RBAC(Role-Based Access Control)——基于角色的访问控制。以产品经理的角度去解析RBAC模型,并分别举例如何运用这套已得到验证的成熟模型。

  1. RBAC模型是什么?
    RBAC是一套成熟的权限模型。在传统权限模型中,我们直接把权限赋予用户。而在RBAC中,增加了“角色”的概念,我们首先把权限赋予角色,再把角色赋予用户。这样,由于增加了角色,授权会更加灵活方便。在RBAC中,根据权限的复杂程度,又可分为RBAC0、RBAC1、RBAC2、RBAC3。其中,RBAC0是基础,RBAC1、RBAC2、RBAC3都是以RBAC0为基础的升级。我们可以根据自家产品权限的复杂程度,选取适合的权限模型。


    image.png
  2. 基本模型RBAC0
    解析:
    RBAC0是基础,很多产品只需基于RBAC0就可以搭建权限模型了。在这个模型中,我们把权限赋予角色,再把角色赋予用户。用户和角色,角色和权限都是多对多的关系。用户拥有的权限等于他所有的角色持有权限之和。
    image.png

    举例:
    譬如我们做一款企业管理产品,如果按传统权限模型,给每一个用户赋予权限则会非常麻烦,并且做不到批量修改用户权限。这时候,可以抽象出几个角色,譬如销售经理、财务经理、市场经理等,然后把权限分配给这些角色,再把角色赋予用户。这样无论是分配权限还是以后的修改权限,只需要修改用户和角色的关系,或角色和权限的关系即可,更加灵活方便。此外,如果一个用户有多个角色,譬如王先生既负责销售部也负责市场部,那么可以给王先生赋予两个角色,即销售经理+市场经理,这样他就拥有这两个角色的所有权限
  3. 角色分层模型RBAC1
    解析:
    RBAC1建立在RBAC0基础之上,在角色中引入了继承的概念。简单理解就是,给角色可以分成几个等级,每个等级权限不同,从而实现更细粒度的权限管理。
    image.png

    举例:
    基于之前RBAC0的例子,我们又发现一个公司的销售经理可能是分几个等级的,譬如除了销售经理,还有销售副经理,而销售副经理只有销售经理的部分权限。这时候,我们就可以采用RBAC1的分级模型,把销售经理这个角色分成多个等级,给销售副经理赋予较低的等级即可。
  4. 角色限制模型RBAC2
    解析:
    RBAC2同样建立在RBAC0基础之上,仅是对用户、角色和权限三者之间增加了一些限制。这些限制可以分成两类,即静态职责分离SSD(Static Separation of Duty)和动态职责分离DSD(Dynamic Separation of Duty)。具体限制如下图:
    image.png

    举例:
    还是基于之前RBAC0的例子,我们又发现有些角色之间是需要互斥的,譬如给一个用户分配了销售经理的角色,就不能给他再赋予财务经理的角色了,否则他即可以录入合同又能自己审核合同;再譬如,有些公司对角色的升级十分看重,一个销售员要想升级到销售经理,必须先升级到销售主管,这时候就要采用先决条件限制了。
  5. 基于RBAC的延展——用户组
    解析:
    基于RBAC模型,还可以适当延展,使其更适合我们的产品。譬如增加用户组概念,直接给用户组分配角色,再把用户加入用户组。这样用户除了拥有自身的权限外,还拥有了所属用户组的所有权限。
    举例:
    譬如,我们可以把一个部门看成一个用户组,如销售部,财务部,再给这个部门直接赋予角色,使部门拥有部门权限,这样这个部门的所有用户都有了部门权限。用户组概念可以更方便的给群体用户授权,且不影响用户本来就拥有的角色权限。

2基于角色和资源的用户权限控制(用SpringMVC实现)

1.准备工作

新建数据库sshwebe:

image.png

建立数据表(由hibernate 对应模型类的映射文件自动建立各表与关系表)
通常,我们会混合使用上述的几种方式。其中,基于角色和资源是目前较为常见的一种实现,一般会有以下几张表:
用户表/学生表(users/t_students):id、用户名、密码、状态(是否可用,下同)
角色表(sb_roles):id、角色名、角色状态
权限表(sb_permissions):id、权限名、权限状态
除了这三张表外,还要两张表来将三者关联起来:
用户角色关联表(sb_students_roles):用户id、角色id(复合主键)
角色权限关联表(sb_roles_permissions):角色id、权限id(复合主键)
然后,我们在相应的controller中通过 annotation,或者在XML中定义相应的permission即可。
注:如果你不想自己实现,可以直接用Spring Security、Shiro等第三方安全框架,只要参照其规范建立几张表,进行一下配置即可。如果要自己实现也不难,这种权限控制模型,有点久是简单,缺点就是,角色被写死在数据库里,修改角色要修改数据库和源码,麻烦,所以使用与角色固定的中小系统,下面我们就通
过过滤器来实现。
初始化表记录:让程序一发布有一个超级管理员
1.学生:stuname:admin,password:admin123,state:1,regDate:2021-10-19
2.角色:roleName:超级管理员,state:1
3.学生-角色表:stu_id:1,roleId:1
建立各模型类
Student,Role,Permission类,Student类前面已有,只是改下:Student中把height字段删除,重新生成get,set和toString方法。
---再生成各自的dao,service层的接口与接口实现类,接口继承BaseDao,BaseService接口。实现类继承(extends)BaseDaoImpl,BaseServiceImpl,执行(implements)各自接口。
Role类:增加关联多对多单向权限类Permission,映射表中Role.hbm.xml,加如下内容。

------------------------------------------------------------------Role.java-----------------------------------------------------------
public class Role {
    private int id;
    private String roleName;
    private Integer state;    //0:表示禁 用,1:表示正常
    private Set permissions;
        get,set,toString()等方法;//右击文件内容处,source---generate....
}
-----------------------------------Role.hbm.xml--------------------------------------------------------------------------------------



    
        
            
            
        
        
            
        
        
            
          

        
           
              
           
           
        

Permission类:

public class Permission {
    private int id;
    private String resources;   //这相权限能访问的资源
    private Integer state;      //状态0:表示禁用,1:表示正常
       set,get,toString()方法。。。。
}

步1:”建立login.jsp文件,并实现http://localhost/项目名/login进行登陆页
1.从别处搞来的样式文件,login.css,login.jsp标签
如图所示它们的存放位置。

image.png

2.控制类中,设置返回login.jsp页。
image.png

image.png

步2:建立登录后的主页main.jsp 主要用于-用户管理--角色管理---权限管理
main.js主要作用是点击左侧的菜单,会在中心区面板上(easyui-tabs选项卡面板)添加选项是同菜单一样的选项。

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>




熊少文管理后台








   
    

Easyui+spring+springmvc+hibernate+根限控制模型

熊少文,欢迎你!

网站首页|帮助中心|安全退出

------------------------------------------------------------------main.js----------------------------------------- $(function(){ $(".sshweb_side_tree li a").bind("click",function(){ var title = $(this).text(); var iconCls = $(this).attr("data-icon"); var url = $(this).attr("data-link"); var iframe = $(this).attr("iframe")==1?true:false; addTab(title,url,iconCls,iframe); }); }); function addTab(title,url,iconCls,iframe){ var tabPanel = $("#sshweb_tabs"); if(!tabPanel.tabs("exists",title)){ var content = ""; if(iframe){ tabPanel.tabs("add",{ title:title, content:content, //