zoukankan      html  css  js  c++  java
  • 纳税服务系统【角色模块、包含权限】

    需求分析

    我们直接来看看原型图,看看需求是怎么样的:

    这里写图片描述

    这里写图片描述

    我们看到上图,就会发现角色模块主要还是CRUD,唯一不同的就是它不再是单独的实体关系。角色与权限是存在关系的。

    之前在Servlet+JSP+JavaBean的时候其实我们已经做过了用户-角色-权限之间的操作【权限管理系统】http://blog.csdn.net/hon_3y/article/details/61926175

    角色与权限应该是多对多的关系的。

    • 一个角色拥有多个权限
    • 一个权限可以被多个角色使用

    进一步分析

    现在我的权限只有5个,有必要使用数据库表吗???没啥必要吧。权限基本就固定下来了。那多对多的关系怎么维护???之前我们使用数据库表就很好做了呀。设计两个实体,使用中间表来描述它们之间的关系就做出来了。

    那现在怎么做呢??一个角色对应多个权限

    这里写图片描述

    我们在数据库中的表就可以这样设计:即使没有权限表,但是我使用了中间表维护了它们的数据。一样可以做到一个角色对应多个权限这样的功能。

    这里写图片描述

    设计实体类

    设计权限常量类

    我们权限是不需要表的,因此我们把各个权限写下来,使用一个集合装载着就行了。当然啦,他们都应该被设计成常量。我们保存在core模块中【被整个系统用到的】

    package zhongfucheng.core.constant;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by ozc on 2017/5/26.
     */
    public class Constant {
    
        /*----------------------系统权限集合--------------------------*/
        public static String PRIVILEGE_XZGL = "xzgl";
        public static String PRIVILEGE_HQFW = "hqfw";
        public static String PRIVILEGE_ZXXX = "zxxx";
        public static String PRIVILEGE_NSFW = "nsfw";
        public static String PRIVILEGE_SPACE = "spaces";
    
    
        //使用一个Map集合来装载着这些权限。
        public static Map<String, String> PRIVILEGE_MAP;
        static {
            PRIVILEGE_MAP = new HashMap<String, String>();
            PRIVILEGE_MAP.put(PRIVILEGE_XZGL, "行政管理");
            PRIVILEGE_MAP.put(PRIVILEGE_HQFW, "后勤服务");
            PRIVILEGE_MAP.put(PRIVILEGE_ZXXX, "在线学习");
            PRIVILEGE_MAP.put(PRIVILEGE_NSFW, "纳税服务");
            PRIVILEGE_MAP.put(PRIVILEGE_SPACE, "我的空间");
        }
    }
    
    

    设计角色类

    我们的角色类应该使用一个Set集合来保存对应的权限数据的,那么Set集合的元素类型是什么呢???想一下…

    之前我们在用的时候,如果有权限表。我们在角色中Set集合的元素应该是Privilege类。但是现在是没有权限表的。我们怎么通过角色来获取所有的权限呢??

    再看回这样ER图:我们在角色Set集合中保存着角色与关系表这个不就行了吗!!!

    这里写图片描述

    于是我们这样设计:

    
    package zhongfucheng.role.entity;
    
    import java.io.Serializable;
    import java.util.Set;
    
    /**
     * Created by ozc on 2017/5/26.
     */
    public class Role implements Serializable {
        private String roleId;
        private String state;
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        private Set<RolePrivilege> rolePrivilegeSet;
    
        public static String USER_STATE_VALID = "1";//有效,
        public static String USER_STATE_INVALID = "0";//无效
    
    
        public String getRoleId() {
            return roleId;
        }
    
        public void setRoleId(String roleId) {
            this.roleId = roleId;
        }
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
        public Set<RolePrivilege> getRolePrivilegeSet() {
            return rolePrivilegeSet;
        }
    
        public void setRolePrivilegeSet(Set<RolePrivilege> rolePrivilegeSet) {
            this.rolePrivilegeSet = rolePrivilegeSet;
        }
    
        public static String getUserStateValid() {
            return USER_STATE_VALID;
        }
    
        public static void setUserStateValid(String userStateValid) {
            USER_STATE_VALID = userStateValid;
        }
    
        public static String getUserStateInvalid() {
            return USER_STATE_INVALID;
        }
    
        public static void setUserStateInvalid(String userStateInvalid) {
            USER_STATE_INVALID = userStateInvalid;
        }
    }
    

    设计角色与权限关系类

    角色与权限关系类只有两个属性:角色的id和权限的code….这两个是外键列。一张表中一定是要有主键列的,于是我们采用的是复合主键的方式。

    对于复合主键,它是要让该类维护一个复合主键类的:

    将主键所对应属性提取出一个类(称之为主键类),并且主键类需要实现Serializable接口,重写hashCode和equals()方法

    
    
    public class RolePrivilege implements Serializable {
    
        private CompositeKey compositeKey;
    
        public CompositeKey getCompositeKey() {
            return compositeKey;
        }
    
        public void setCompositeKey(CompositeKey compositeKey) {
            this.compositeKey = compositeKey;
        }
    }
    
    

    复合主键类

    按照ER图,我们复合主键就两个属性:role_id和code。。

    但是呢,我们想一下需求:在获取角色所有权限的时候,Set集合装载着角色与权限的关系,而角色与权限的关系装载着role_id和code。而很有可能:在我查看用户所拥有角色的时候,想要得到角色的名称。这里仅仅查出来的是角色id,还要通过角色id得到角色的名称…这样就有点麻烦了。于是我们写成Role对象。到时候就能直接获取了。

    
    package zhongfucheng.role.entity;
    
    import java.io.Serializable;
    
    /**
     * Created by ozc on 2017/5/26.
     */
    public class CompositeKey implements Serializable {
    
    
        private String code;
        private Role role;
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            CompositeKey that = (CompositeKey) o;
    
            if (code != null ? !code.equals(that.code) : that.code != null) return false;
            return role != null ? role.equals(that.role) : that.role == null;
    
        }
    
        @Override
        public int hashCode() {
            int result = code != null ? code.hashCode() : 0;
            result = 31 * result + (role != null ? role.hashCode() : 0);
            return result;
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public Role getRole() {
            return role;
        }
    
        public void setRole(Role role) {
            this.role = role;
        }
    }
    
    

    角色映射表配置

    
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="zhongfucheng.role.entity.Role" table="role">
            <id name="roleId" type="java.lang.String">
                <column name="roleId" length="32" />
                <generator class="uuid.hex" />
            </id>
            <property name="state" type="java.lang.String">
                <column name="state" length="1" />
            </property>
            <property name="name" type="java.lang.String">
                <column name="name" length="20" not-null="true" />
            </property>
            <!--
                一方维护多方的数据,inverse设置为true,没有控制权限
                设置级联保存更新,在保存角色的时候,将权限也保存起来了。
                不设置懒加载,直接获取到权限的数据
            -->
            <set name="rolePrivilegeSet" lazy="false" inverse="true" cascade="save-update" >
                <key>
                    <column name="role_id"></column>
                </key>
                <one-to-many class="zhongfucheng.role.entity.RolePrivilege" ></one-to-many>
            </set>
        </class>
    
    </hibernate-mapping>
    

    角色与权限映射表配置

    
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="zhongfucheng.role.entity.RolePrivilege" table="role_privilege">
            <composite-id name="id" class="zhongfucheng.role.entity.CompositeKey">
                <key-many-to-one name="role" class="zhongfucheng.role.entity.Role" lazy="false">
                    <column name="role_id "></column>
                </key-many-to-one>
                <key-property name="code" type="java.lang.String">
                    <column name="code"></column>
                </key-property>
            </composite-id>
        </class>
    </hibernate-mapping>
    

    Role模块的CRUD

    没啥好说的,我们在User模块中已经写过了。我们可以直接复制过来,然后将不要的功能去掉。

    • 将全部的User改成Role
    • 将全部的user改成role

    dao–>service—>action这样改完,就有了Role模块的CRUD了。

    最后:

    • Spring总配置文件中加载role模块实体映射文件,加载role模块的bean文件。
    • Struts总配置文件中加载role模块的Struts配置文件。

    添加模块

    把权限的集合带过去给JSP页面显示出来,JSP使用Struts的checkbox进行遍历【很好用】

    
        public String addUI() {
    
            ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);
            return "addUI";
        }

    使用checkbox标签遍历

            <tr>
                <td class="tdBg" width="200px">角色权限:</td>
                <td>
    
                    <%--
    
                    checkboxlist:自动把Map集合遍历出来,生成对应的key value,Map集合的key作为checkbox的key,value作为checkbox的value
                        list:集合
                        name:把数据带过去给服务器
    
                    --%>
                        <s:checkboxlist list="#privilegeMap" name="privilegeIds"/>
                </td>
            </tr>
    

    这里写图片描述

    这里写图片描述


    
        /************数据自动封装权限的id*************************/
        private String[] privilegeIds;
    
        public String[] getPrivilegeIds() {
            return privilegeIds;
        }
    
        public void setPrivilegeIds(String[] privilegeIds) {
            this.privilegeIds = privilegeIds;
        }

    处理角色与权限的关系。在配置中使用了级联保存,因此可以直接保存数据

        public String add() throws IOException {
            if (role != null) {
                //处理角色与权限的关系
                if (privilegeIds != null) {
                    HashSet<RolePrivilege> set = new HashSet<>();
                    //得到每一个权限的值--->entity给出对应的构造方法...
                    for (int i = 0; i < privilegeIds.length; i++) {
                        set.add(new RolePrivilege(new CompositeKey(role, privilegeIds[i])));
                    }
                    role.setRolePrivilegeSet(set);
                }
                roleServiceImpl.save(role);
                //跳转到列表显示页面
                return "list";
            }
            return null;
        }
    

    这里写图片描述

    这里写图片描述

    显示模块

    在显示模块中,主要是显示角色的权限中有点绕…..

    角色的权限用set集合保存起来,set集合元素是角色与权限的关系,角色与权限是一个类,该类保存着主键类,主键类存储的是角色和权限code。

    我们的目的是:得到角色含有的权限。而目前为止,我们最多只能得到每个权限code值:

    这里写图片描述

    而我们想要显示的是权限的名称,于是我们得把权限集合传过去,根据code得到权限的名称

    
        public String listUI()   {
    
            roleList = roleServiceImpl.findObjects();
    
            ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);
            return "listUI";
        }

    JSP页面取值:注意懒加载的问题,设定不要懒加载。不然会出现: java.io.IOException: Stream closed

    
        <s:iterator value="rolePrivilegeSet">
           <s:property value="#privilegeMap[compositeKey.code]"/>
        </s:iterator>

    这里写图片描述


    单个删除功能

    跳转到Action中处理,把id传递过去…

    
        function doDelete(id) {
            document.forms[0].action = "${basePath}role/role_delete.action?role.roleId="+id;
            document.forms[0].submit();
        }

    判断是否为空,不为空就删除。返回到列表页面

    
    2017/5/31 12:59:27     //删除
        public String delete() {
            if (role != null && role.getRoleId() != null) {
                roleServiceImpl.delete(role.getRoleId());
            }
            return "list";
        }

    修改模块

    数据回显页面,主要就是角色的权限那里怎么回显。我们把所有的权限带过去,用字符串数组记录当前角色有什么权限

    
            //得到所有的权限
            ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);
    
            //外边已经传了id过来了,我们要找到id对应的Role
            if (role != null && role.getRoleId() != null) {
                //直接获取出来,后面JSP会根据Role有getter就能读取对应的信息!
                role = roleServiceImpl.findObjectById(role.getRoleId());
    
                //得到角色所有的权限,把它封装到privilegeIds字符数组中。
                //处理权限回显
                if (role.getRolePrivilegeSet() != null) {
                    privilegeIds = new String[role.getRolePrivilegeSet().size()];
    
                    int i = 0;
                    for (RolePrivilege rp : role.getRolePrivilegeSet()) {
                        privilegeIds[i++] = rp.getCompositeKey().getCode();
                    }
                }
    
            }
            return "editUI";

    在JSP页面,使用checkboxlist标签进行遍历。

    
    <s:checkboxlist list="#privilegeMap" name="privilegeIds" ></s:checkboxlist> 

    这里写图片描述


    得到JSP传递过来的ids,封装成一个set集合。将set集合赋值给role对象。

    
       public String edit() throws IOException {
            //Struts2会自动把JSP带过来的数据封装到Role对象上
            if (role.getRoleId() != null && role != null) {
    
                Set<RolePrivilege> set = new HashSet<>();
                //得到修改的权限id,封装到set集合中。
                for (String privilegeId : privilegeIds) {
                    set.add(new RolePrivilege(new CompositeKey(role, privilegeId)));
                }
                role.setRolePrivilegeSet(set);
    
                roleServiceImpl.update(role);
            }
            return "list";
        }

    仅仅是使用update(role)方法是不够的,因此Hibernate在更新操作的时候,会先把数据查询出来。当我们更改角色权限的时候,它会将我们已有的权限保留下来,如果有新的就继续添加。它不会把我们没勾选的剔除的

    因此,我们需要在更新的之前,把当前角色所有的权限给删了

    
            //在修改之前,把角色的所有权限给删除了。不然会遗留之前的权限下来。
            roleDaoImpl.deleteRolePrivilegeByRoleId(role.getRoleId());
    
        /***
         * 根据角色id删除所有的权限
         * */
        @Override
        public void deleteRolePrivilegeByRoleId(String roleId) {
    
            String sql = "DELETE FROM RolePrivilege WHERE compositeKey.role.roleId= ?";
    
            Query query = getSession().createQuery(sql);
            query.setParameter(0, roleId);
            query.executeUpdate();
        }

    效果:

    这里写图片描述

  • 相关阅读:
    mysql 双机互备份
    ubuntu12.04 qtcreate支持中文输入
    新版IDEA 2020.1遇到的坑Error:(3,32)java:程序包org.springframework.boot不存在Error:
    No partition predicate found for Alias "TS" Table ""
    SQL语句中sum与count的区别
    :line 1:100 cannot recognize input near '<EOF>' '<EOF>' '<EOF>' in statement
    mysql计算某个字段最长值
    mysql字段varchar长度分配对性能的影响
    【MySQL】NOT NULL default 0
    FAILED: NoMatchingMethodException No matching method for class org.apache.hadoop.hive.ql.udf.UDFToString with (struct<hashtags:array<string>
  • 原文地址:https://www.cnblogs.com/zhong-fucheng/p/7202920.html
Copyright © 2011-2022 走看看