纳税服务系统四(角色模块)【角色与权限、角色与用户】

OA系统四级模块编写测试用例(角色模块) 新增角色模块 (1)系统需求 (2)需求分析 (3)编写用例 (4)导入用例 先创建数据分析表,将控件的有效、无效等价类记录好。再创建新的扩展名为.csv的记录测试用例的表格文件。 用测试人员1的账号登录 excle表中按住ctrl键往下拖拽的时候会自动复制上一行,否则数字就会递增 下载的模板的格式和写用例的表的格式要一致,模块信息就从模板中找到复制进去。 修改角色模块 和新增角色的步骤一样。 (1)系统需求 (2)需求分析 (3)编写用例 (4)导入用例 和新增角 阅读详情

需求分析

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

640?wx_fmt=png
这里写图片描述
640?wx_fmt=png
这里写图片描述

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

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

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

进一步分析

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

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

640?wx_fmt=png
这里写图片描述

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

640?wx_fmt=png
这里写图片描述

设计实体类

设计权限常量类

我们权限是不需要表的,因此我们把各个权限写下来,使用一个集合装载着就行了。当然啦,他们都应该被设计成常量。我们保存在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, "我的空间");    }}

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集合中保存着角色与关系表这个不就行了吗!!!

640?wx_fmt=png
这里写图片描述

于是我们这样设计:

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;    }}

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;    }}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;    }}

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>
<!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>

------ - - - -更新

上面我们是将inverse属性设置为true的,但是下面的代码还是使用了一的一方来维护多个一方的数据。这样是不合理的。

角色与权限映射表配置

<?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>
<!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模块中已经写过了。我们可以直接复制过来,然后将不要的功能去掉。

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

最后:


添加模块

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

    public String addUI() {        ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);        return "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>
           <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>
640?wx_fmt=png
这里写图片描述
640?wx_fmt=png
这里写图片描述

    /************数据自动封装权限的id*************************/    private String[] privilegeIds;    public String[] getPrivilegeIds() {        return privilegeIds;    }    public void setPrivilegeIds(String[] privilegeIds) {        this.privilegeIds = privilegeIds;    }
   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;    }
       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;
   }
640?wx_fmt=png
这里写图片描述
640?wx_fmt=png
这里写图片描述

显示模块

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

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

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

640?wx_fmt=png

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

    public String listUI()   {        roleList = roleServiceImpl.findObjects();        ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP);        return "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>
      <s:property value="#privilegeMap[compositeKey.code]"/>
   </s:iterator>
640?wx_fmt=png
这里写图片描述

单个删除功能

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

    function doDelete(id) {        document.forms[0].action = "${basePath}role/role_delete.action?role.roleId="+id;        document.forms[0].submit();    }
       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";    }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";
       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>    </s:checkboxlist>    
640?wx_fmt=png
这里写图片描述

得到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";    }
       //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());
       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();    }
   @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();
   }

效果:

640?wx_fmt=gif
这里写图片描述

用户与角色之间的关系

我们在做用户模块的时候,漏掉了最后一个功能。在新增功能中是可以选择角色的。

640?wx_fmt=png
这里写图片描述

用户与角色之间的关系也是多对多

640?wx_fmt=png
这里写图片描述

现在呢,我们的用户表已经是写的了。我们最好就不要修改原有的用户表数据。那我们在不修改用户表代码的情况下,又怎么来实现多对多呢??

跟角色与权限是一样的。使用中间表来维护它们的关系就行了。

    用户:user    用户id,名称...    1      用户1    2      用户2    用户角色:user_role    用户id,角色id    1       1    1       2    2       2    角色:role    角色Id,名称    1      管理员    2      一般用户
   1      用户1
   2      用户2

   用户角色:user_role
   用户id,角色id
   1       1
   1       2
   2       2


   角色:role
   角色Id,名称
   1      管理员
   2      一般用户

设计中间表

public class UserRole implements Serializable {    private UserRoleId userRoleId;    public UserRoleId getUserRoleId() {        return userRoleId;    }    public void setUserRoleId(UserRoleId userRoleId) {        this.userRoleId = userRoleId;    }}class UserRole implements Serializable {

   private UserRoleId userRoleId;

   public UserRoleId getUserRoleId() {
       return userRoleId;
   }

   public void setUserRoleId(UserRoleId userRoleId) {
       this.userRoleId = userRoleId;
   }
}

主键表

public class UserRoleId implements Serializable {    private String user_id;    //在使用的时候,Role相关的数据会用得特别多。为了方便使用了Role对象。而user就不需要使用User对象了。    private Role role;    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (o == null || getClass() != o.getClass()) return false;        UserRoleId that = (UserRoleId) o;        if (user_id != null ? !user_id.equals(that.user_id) : that.user_id != null) return false;        return role != null ? role.equals(that.role) : that.role == null;    }    @Override    public int hashCode() {        int result = user_id != null ? user_id.hashCode() : 0;        result = 31 * result + (role != null ? role.hashCode() : 0);        return result;    }    public String getUser_id() {        return user_id;    }    public void setUser_id(String user_id) {        this.user_id = user_id;    }    public Role getRole() {        return role;    }    public void setRole(Role role) {        this.role = role;    }}class UserRoleId implements Serializable {

   private String user_id;

   //在使用的时候,Role相关的数据会用得特别多。为了方便使用了Role对象。而user就不需要使用User对象了。
   private Role role;


   @Override
   public boolean equals(Object o) {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;

       UserRoleId that = (UserRoleId) o;

       if (user_id != null ? !user_id.equals(that.user_id) : that.user_id != null) return false;
       return role != null ? role.equals(that.role) : that.role == null;

   }

   @Override
   public int hashCode() {
       int result = user_id != null ? user_id.hashCode() : 0;
       result = 31 * result + (role != null ? role.hashCode() : 0);
       return result;
   }

   public String getUser_id() {
       return user_id;
   }

   public void setUser_id(String user_id) {
       this.user_id = user_id;
   }

   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.user.entity.UserRole" table="user_role">            <composite-id  name="userRoleId" class="zhongfucheng.user.entity.UserRoleId">                <!--manytoone可以生成外键字段。-->                <key-many-to-one name="role" class="zhongfucheng.role.entity.Role" column="role_id" lazy="false"/>                <key-property name="user_id" column="user_id" type="java.lang.String"/>            </composite-id>        </class>    </hibernate-mapping>
   <!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.user.entity.UserRole" table="user_role">
           <composite-id  name="userRoleId" class="zhongfucheng.user.entity.UserRoleId">

               <!--manytoone可以生成外键字段。-->
               <key-many-to-one name="role" class="zhongfucheng.role.entity.Role" column="role_id" lazy="false"/>

               <key-property name="user_id" column="user_id" type="java.lang.String"/>
           </composite-id>
       </class>

   </hibernate-mapping>

增加模块

在跳转到JSP页面的前,把所有的角色找出来。放到request域对象中,让JSP页面显示出来。

    public String addUI() {        //把所有的角色查询出来,带过去给JSP页面显示        ActionContext.getContext().getContextMap().put("roleList", roleServiceImpl.findObjects());        return "addUI";    }

       //把所有的角色查询出来,带过去给JSP页面显示
       ActionContext.getContext().getContextMap().put("roleList", roleServiceImpl.findObjects());

       return "addUI";
   }
    <%--        list是集合对象        name是要带给服务器端的字符串数组。        listkey 是集合元素对象的id        listValue 是集合元素对象的名字    --%>    <s:checkboxlist list="#roleList" name="userRoleIds" listKey="roleId" listValue="name"/>
   <s:checkboxlist list="#roleList" name="userRoleIds" listKey="roleId" listValue="name"/>
640?wx_fmt=png
这里写图片描述

编辑模块

编辑回显数据

在编辑模块中,需要将该用户所拥有的角色查询出来。然后把查询出来的id值放到数组中。

    public String editUI() {        //把所有的角色查询出来,带过去给JSP页面显示        ActionContext.getContext().getContextMap().put("roleList", roleServiceImpl.findObjects());        //外边已经传了id过来了,我们要找到id对应的User        if (user != null &&user.getId() != null  ) {            //直接获取出来,后面JSP会根据User有getter就能读取对应的信息!            user = userServiceImpl.findObjectById(user.getId());            //通过用户的id得到所拥有UserRole            List<UserRole> roles = userServiceImpl.findRoleById(user.getId());            //把用户拥有角色的id填充到数组中,数组最后回显到JSP页面            int i=0;            userRoleIds =  new String[roles.size()];            for (UserRole role : roles) {                userRoleIds[i++] = role.getUserRoleId().getRole().getRoleId();            }        }        return "editUI";    }

       //把所有的角色查询出来,带过去给JSP页面显示
       ActionContext.getContext().getContextMap().put("roleList", roleServiceImpl.findObjects());

       //外边已经传了id过来了,我们要找到id对应的User
       if (user != null &&user.getId() != null  ) {
           //直接获取出来,后面JSP会根据User有getter就能读取对应的信息!
           user = userServiceImpl.findObjectById(user.getId());

           //通过用户的id得到所拥有UserRole
           List<UserRole> roles = userServiceImpl.findRoleById(user.getId());
           //把用户拥有角色的id填充到数组中,数组最后回显到JSP页面
           int i=0;
           userRoleIds =  new String[roles.size()];
           for (UserRole role : roles) {
               userRoleIds[i++] = role.getUserRoleId().getRole().getRoleId();
           }

       }
       return "editUI";
   }

JSP通过checkboxlist进行回显,指定了name值就能够自动判定我们的用户拥有的角色是什么了。

    <s:checkboxlist list="#roleList" name="userRoleIds" listKey="roleId" listValue="name"></s:checkboxlist></s:checkboxlist>
640?wx_fmt=png
这里写图片描述

处理编辑操作

在更新之前,首先删除用户与角色之间的关系【历史遗留问题】,如果不删除,那么用户所拥有的角色就一直保留着。无论你在JSP页面有没有勾选。

    public String edit() throws IOException {        //Struts2会自动把JSP带过来的数据封装到User对象上        if (user.getId() != null && user != null) {            if (headImg != null) {                //得到要把头像上传到服务器的路径                javax.servlet.ServletContext servletContext = ServletActionContext.getServletContext();                String realPath = servletContext.getRealPath("upload/user");                //由于用户上传的名字可能会相同,如果相同就被覆盖掉,因此我们要修改上传文件的名字【独一无二】                headImgFileName = UUID.randomUUID().toString() + headImgFileName.substring(headImgFileName.lastIndexOf("."));                FileUtils.copyFile(headImg, new File(realPath, headImgFileName));                //设置图片与用户的关系                user.setHeadImg(headImgFileName);            }            if (userRoleIds != null) {                //删除用户与角色之间的关系【历史遗留问题】                userServiceImpl.deleteUserRoleById(userRoleIds);                //保存用户与角色。                userServiceImpl.saveUserAndRole(user,userRoleIds);            }        }        return "list";    }
       //Struts2会自动把JSP带过来的数据封装到User对象上
       if (user.getId() != null && user != null) {
           if (headImg != null) {

               //得到要把头像上传到服务器的路径
               javax.servlet.ServletContext servletContext = ServletActionContext.getServletContext();
               String realPath = servletContext.getRealPath("upload/user");
               //由于用户上传的名字可能会相同,如果相同就被覆盖掉,因此我们要修改上传文件的名字【独一无二】
               headImgFileName = UUID.randomUUID().toString() + headImgFileName.substring(headImgFileName.lastIndexOf("."));
               FileUtils.copyFile(headImg, new File(realPath, headImgFileName));

               //设置图片与用户的关系
               user.setHeadImg(headImgFileName);
           }
           if (userRoleIds != null) {

               //删除用户与角色之间的关系【历史遗留问题】
               userServiceImpl.deleteUserRoleById(userRoleIds);
               //保存用户与角色。
               userServiceImpl.saveUserAndRole(user,userRoleIds);
           }
       }
       return "list";
   }

调用保存用户与角色的关系。如果id不是为空的,那么就执行更新,如果id为空,就执行保存。

    @Override    public void saveUserAndRole(User user, String... userRoleIds) {        //保存或更新用户        if (user.getId() != null) {            userDaoImpl.update(user);        } else {            userDaoImpl.save(user);        }        //判断有没有把id带过来        if (userRoleIds != null) {            for (String userRoleId : userRoleIds) {                System.out.println(userRoleId);                userDaoImpl.saveUserRole(new UserRole(new UserRoleId(user.getId(), new Role(userRoleId))));            }        }    }
   public void saveUserAndRole(User user, String... userRoleIds) {

       //保存或更新用户
       if (user.getId() != null) {
           userDaoImpl.update(user);
       } else {
           userDaoImpl.save(user);
       }
       //判断有没有把id带过来
       if (userRoleIds != null) {
           for (String userRoleId : userRoleIds) {
               System.out.println(userRoleId);
               userDaoImpl.saveUserRole(new UserRole(new UserRoleId(user.getId(), new Role(userRoleId))));
           }

       }
   }

总结

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y


WorkBuddy智能体实战:三步搭建自动周报汇总流程 在数字化办公时代,信息分散于聊天记录、多维表格和笔记工具之中,手动收集与整理成为效率瓶颈。AI智能体技术通过连接器、自定义指令与定时触发,正在改变这一现状。其核心原理是将重复性事务拆解为“数据读取—语义理解—内容生成—服务调用”的标准化流水线,让非技术用户也能自主配置自动化任务。这类能力广泛应用于周报汇总、会议纪要生成、定时消息推送等高频办公场景,显著减少人工搬运与格式调整的耗时。本文基于腾讯WorkBuddy的实际使用经验,介绍如何通过创建Skill技能、配置数据源连接器、编写精准处理规则,实现跨应用的周 阅读详情

相关推荐

Lumerical官方案例、FDTD时域有限差分法仿真学习(十三)——多模干涉耦合器(MMI)

计算通过 1×2 端口多模干涉 (MMI) 耦合器的宽带传输和光损耗。 使用设备 S 参数在 INTERCONNECT 中创建 MMI 的紧凑模型。 它还展示了如何使用 CML 编译器提取这些参数以生成紧凑模型。 一、概述 了解模拟工作流程和关键结果 低损耗光合路器和分路器是基于 Mach-Zehnder 的光调制器的基本组件,并且是集成电路的关键组成部分。通过在输入/输出波导处使用线性锥形确保输入/输出波导的模式与干涉区域之间的

weixin_45719141的博客 1万+

java部门跟用户的关系,javaEE 用户、部门、角色、权限实体的关系设计与hibernate映射配置文件关系总结...

文章中的项目文件已经放到Github上,欢迎大家Follow,star,一:设计实体,我这里通过uml设计,然后直接可以生成java实体类(方便查看各个类的关系)(1)用户登录类User与用户详细信息类UserDetails为一对一关系;(2)用户详细信息类UserDetails与部门为多对一关系;(一个部门有多个用户)(3)部门类是自关联的,有上级部门;(3)用户详细类UserDetails与角...

weixin_39616348的博客 591

让Claude连续写代码24小时会发生什么?揭秘长时运行”架构背后的工程逻辑与未来

AI长时运行实验揭示软件开发新范式 Claude Opus通过Harness框架24小时独立开发全栈应用的成功实验,展示了AI从辅助工具向异步协作者的进化。实验采用"上下文轮转"机制解决记忆管理难题,将任务拆解为微周期并通过文件系统同步进度。核心突破在于:1)TDD成为AI自治基石,200+测试用例确保开发不偏航;2)文件取代对话成为AI间高效沟通介质;3)开发者角色重构为需求定义和框架设计者。该实验证明,通过严谨的架构约束和验收标准,AI可完成复杂长周期任务,预示着软件开发将从手工作坊

老孙 | Ethan Sun 的博客:AI 智能体与 AI 原生软件的工程实践 1093

Role分析模式(一) 角色对象基本概念

概要在任何应用系统中,每一个对象都可能扮演多种角色,你在家里是父亲,在公司则可能是一个程序员,一个为你提供原材料的公司可能同时又是你的客户。。,这样的问题一次又一次的出现,我经常看到应用系统不能很好处理这些问题,在本文中,我将仔细描述这一重要的分析模式,并使用TAOERP 基本业务元素(TBCC)展示如何使用这一分析模式处理组织机构相关的问题。一个应用系统经常需要某一个对象在不同的上下文中具有不同

ivanlovetracy::伊凡::的专栏 2224

POWER(十一)charge pump原理

电荷泵是一种基于电容充放电原理的DC-DC转换电路,通过开关控制实现电压转换,包括升压、降压和负压输出。其核心是利用电荷守恒原理,通过电容存储和转移电荷来改变输出电压。典型拓扑结构包括倍压电路和多阶升压电路,具有结构简单、体积小等优势。关键参数包括转换效率、输出电流能力和开关频率,适用于芯片供电、显示屏驱动等低功耗场景。LVDS部分补充说明了自举电路在驱动电路中的应用及其自同步特性。

zhlwsh的博客 2816

AI大模型应用性能核心指标:TTFT 与 TPOT 详解

这两个指标专门衡量大模型流式响应性能,是评估用户体验的关键指标。· 是什么:从请求到第一个输出的等待时间· 为什么重要:决定用户的第一印象和响应感知· 优化方向:模型加载、预处理、冷启动优化· 行业标准:最好<500ms,可接受<1.5s· 是什么:每个输出token的平均生成时间· 为什么重要:决定流式输出的流畅度和总完成时间· 优化方向:推理引擎、内存带宽、批处理优化· 行业标准:最好<50ms/token,可接受<100ms/token在Dify/大模型应用中的意义。

lovehu6686的博客 3967

实现自己的权限管理系统(十一):角色用户模块、角色权限模块、权限过滤

前面弄了那么多,都是单独的模块。现在我们需要把用户和权限通过角色关联起来。 一、角色权限模块 1、角色的权限列表更新操作 public void changeRoleAcls(int roleId, List<Integer> aclIdList) { //取出当前角色已分配的权限ID List<Integer> originAclI...

LinDongTian 4916

TOGAF架构内容—TOGAF 内容框架和企业元模型

TOGAF架构内容—TOGAF 内容框架和企业元模型

深圳市多克创新科技有限公司 1664

java纳税服务_纳税服务系统【角色模块、包含权限】

需求分析我们直接来看看原型图,看看需求是怎么样的:我们看到上图,就会发现角色模块主要还是CRUD,唯一不同的就是它不再是单独的实体关系。角色与权限是存在关系的。之前在Servlet+JSP+JavaBean的时候其实我们已经做过了用户-角色-权限之间的操作【权限管理系统】http://blog.youkuaiyun.com/hon_3y/article/details/61926175角色与权限应该是多对多的...

weixin_33196106的博客 179

【100%通过率】华为od统一考试B卷【查找接口成功率最优时间段】Python 实现

服务之间交换的接口成功率作为服务调用关键质量特性,某个时间段内的接口失败率使用一个数组表示,数组中每个元素都是单位时间内失败率数值,数组中的数值为0~100的整数, 给定一个数值(minAverageLost)表示某个时间段内平均失败率容忍值,即平均失败率小于等于minAverageLost,找出数组中最长时间段,如果未找到则直接返回NULL。

MISAYAONE的博客 5869

嵌入式工程师成长之路(2)——电路设计

为什么你的电源模块总是发热炸机?DC/DC和LDO选型的“潜规则”你踩坑了吗? LM2596降压芯片用错电容导致输出振荡?LED恒流驱动设计让灯珠寿命缩水50%?24V转12V方案成本超预算被老板狂喷?——这些血泪教训,谁能懂得!

云轩阁 13万+

java纳税服务_纳税服务系统【总结】

正版包邮spring响应式编程spring73.3元包邮(需用券)去购买 >纳税服务系统总结纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了)我跟着练习一步一步完成需求,才发觉原来Java是这样用来做网站的,Java有那么多的类库,页面的效果(图表、日期选择器等等)是通过Ja...

weixin_39855843的博客 231

深入YOLOv8内部核心:用RepNCSPELAN4深度重构主干网络,即插即用的高效涨点方案

本文提出了一种改进YOLOv8目标检测模型的方法,通过在YOLOv8中引入RepNCSPELAN模块来提高检测性能。该模块融合了RepVGG重参数化思想与CSP-ELAN结构,在保持推理速度的同时增强特征表达能力。实验结果表明,改进后的RepNCSPELAN-YOLOv8相比原模型在多项指标上均有提升:准确率从0.84提高到0.86,召回率从0.72提升至0.81,mAP50和mAP50-95也分别提高了0.06和0.04。文章详细介绍了模块设计原理和移植步骤,包括配置文件创建、代码修改等关键环节,为YOL

FJN110的博客 187

纳税服务系统【角色模块、包含权限】

需求分析我们直接来看看原型图,看看需求是怎么样的:我们看到上图,就会发现角色模块主要还是CRUD,唯一不同的就是它不再是单独的实体关系。角色与权限是存在关系的。之前在Servlet+JSP+JavaBean的时候其实我们已经做过了用户-角色-权限之间的操作【权限管理系统】http://blog.youkuaiyun.com/hon_3y/article/details/61926175角色与权限应该是多对多的关

zhong_fucheng 922

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

java纳税服务_纳税服务系统总结

纳税服务系统总结纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了)我跟着练习一步一步完成需求,才发觉原来Java是这样用来做网站的,Java有那么多的类库,页面的效果(图表、日期选择器等等)是通过JavaScript组件来显示,调用后端代码来获取数据从而显示出来的。通过这次的项目开...

weixin_42515225的博客 155

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

纳税服务系统【总结】

纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一步一步完成需求,才发觉原来Java是这样用来做网站的,Java有那么多的类库,页面的效果(图表、日期选择器等等)是通过JavaScript组件来显示,调用后端代码来获取数据从而显示出来的。 通过...

3y 1181

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

纳税服务系统【角色与用户】

用户与角色之间的关系我们在做用户模块的时候,漏掉了最后一个功能。在新增功能中是可以选择角色的。用户与角色之间的关系也是多对多 一个用户对应多个角色 一个角色可以被多个用户使用。 现在呢,我们的用户表已经是写的了。我们最好就不要修改原有的用户表数据。那我们在不修改用户表代码的情况下,又怎么来实现多对多呢??跟角色与权限是一样的。使用中间表来维护它们的关系就行了。 用户:user 用户i

zhong_fucheng 553

纳税服务系统九【登陆、权限拦截、页面嵌套】

tags: 纳税服务系统项目 前言 到目前为止,我们已经写了用户模块和角色模块了。也已经把系统的首页和子系统的首页配置好了。我们的系统是需要登陆后才能访问的。 因此,本博文主要讲解登陆模块、权限拦截 登陆模块 编写Action与配置文件 引入对应的JSP页面 编写Action处理请求和对应的配置文件: 效果: Action处理 在常量类中保存着一个Session的标识: /...

weixin_33817333的博客 148

JAVA缴税_纳税服务系统【总结】

纳税服务系统总结纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了)我跟着练习一步一步完成需求,才发觉原来Java是这样用来做网站的,Java有那么多的类库,页面的效果(图表、日期选择器等等)是通过JavaScript组件来显示,调用后端代码来获取数据从而显示出来的。通过这次的项目开...

weixin_28882177的博客 371
上一篇: 纳税服务系统二(用户模块)【POI、用户唯一性校验】
下一篇: 纳税服务系统一(用户模块)【简单增删改查、日期组件、上传和修改头像】...
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值