业务描述

  • 权限管理子系统设计中都会有一个角色管理的模块,不同角色可能有不同或相同资源的访问权限

    系统设计

    原型设计

  • 角色列表页面

image.png

  • 角色添加页面

image.png

  • 角色修改页面

image.png

表设计

  • common模块中

    核心API设计

    image.png

    逻辑实现

    领域对象POJO

    ```java package com.cy.pj.sys.pojo;

@Data public class SysRole implements Serializable { private static final long serialVersionUID = 3232155697809432339L; //角色ID private Integer id; //角色名称 private String name; //菜单ID private List menuIds; //备注 private String remark; //创建时间 //@JsonFormat(pattern = “yyyy/MM/dd HH:mm:ss”,timezone = “GMT+8”) private Date createdTime; //@JsonFormat(pattern = “yyyy/MM/dd HH:mm:ss”,timezone = “GMT+8”) private Date modifiedTime; //创建用户 private String createdUser; //修改用户 private String modifiedUser; }

  1. <a name="PftZB"></a>
  2. ### Dao层
  3. - Dao层接口
  4. ```java
  5. package com.cy.pj.sys.dao;
  6. /**创建角色数据逻辑访问对象,基于此对象访问数据库中角色相关数据*/
  7. @Mapper
  8. public interface SysRoleDao {
  9. /**
  10. * 基于条件查询角色信息
  11. * @param:role封装了查询条件的对象
  12. * @return 查询到的结果
  13. */
  14. List<SysRole> selectRoles(SysRole entity);
  15. /**
  16. * 基于id查找对应的角色,因为修改的时候需要先对这行记录查询出来,在原有的基础上修改
  17. * @param id 角色id
  18. * @return 查找到具体角色对象
  19. */
  20. SysRole selectById(Integer id);
  21. /**
  22. * 向表中新增一条角色信息
  23. * @param entity 封装了要新增的角色信息的对象
  24. * @return 新增的行数
  25. */
  26. int insertRole(SysRole entity);
  27. /**
  28. * 基于角色id更新角色信息
  29. * @param entity 封装了要新增的角色信息的对象
  30. * @return 更新的行数
  31. */
  32. int updateRole(SysRole entity);
  33. /**
  34. * 查询角色id和角色name,
  35. * 每行记录封装为一个CheckBox对象,(复选框的信息展示)
  36. * 后续在为用户分配角色时会用到。
  37. * @return
  38. */
  39. @Select("select id,name from sys_roles")
  40. List<CheckBox> selectCheckRoles();
  41. }
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.cy.pj.sys.dao.SysRoleDao">
    <select id="selectRoles" resultType="com.cy.pj.sys.pojo.SysRole">
        select id,name,remark,createdTime,modifiedTime,createdUser,modifiedUser
        from sys_roles
        <where>
            <if test="name!=null and name!=''">
                name like concat("%",#{name},"%")
            </if>
        </where>
        order by createdTime desc
    </select>
    <!--
    1)useGeneratedKeys="true" 表示获取insert操作时写入到数据库的自增主键值
    2)keyProperty="id" 将自增主键值赋值给参数对象的id属性,获得id用于写入角色和菜单关系的数据逻辑层操作,SysRoleMenuMapper.xml
    -->
    <insert id="insertRole" parameterType="com.cy.pj.sys.pojo.SysRole"
            useGeneratedKeys="true"
            keyProperty="id">
        insert into sys_roles
        (name,remark,createdTime,modifiedTime,createdUser,modifiedUser)
        values
        (#{name},#{remark},now(),now(),#{createdUser},#{modifiedUser})
    </insert>


    <!--基于id查询角色以及角色对应的菜单信息,多个菜单用集合Collection接收,假如是对象用association接收
    resultMap是mybatis中提供的高级映射元素,应用场景:
    1)表中字段名与类中属性名不匹配时
    2)多表关联查询映射
    3)多表嵌套查询映射-->
    <resultMap id="roleMenu" type="com.cy.pj.sys.pojo.SysRole">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="remark" column="remark"/>
        <collection property="menuIds" ofType="integer">
            <result column="menu_id" />
        </collection>
    </resultMap>
    <select id="selectById" resultMap="roleMenu">
        select r.id,r.name,r.remark,rm.menu_id
        from sys_roles r 
        left join sys_role_menus rm
        on r.id=rm.role_id
        where r.id=#{id}
    </select>

    <update id="updateRole">
        update sys_roles
        set name = #{name},
            remark = #{remark},
            modifiedTime = now(),
            modifiedUser = #{modifiedUser}
        where id=#{id}
    </update>
</mapper>
  • 角色菜单关系数据 ```java package com.cy.pj.sys.dao;

@Mapper public interface SysRoleMenuDao { /**

 * 新增角色菜单关系数据
 * @param roleId
 * @param menuIds
 * @return
 */
int insertRoleMenus(Integer roleId, List<Integer> menuIds);

/**
 * 基于角色id删除角色和菜单关系数据
 * @param roleId 角色id
 * @return 删除的行数
 */
@Delete("delete from sys_role_menus where role_id=#{role_id}")
int deleteByRoleId(Integer roleId);

}

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.cy.pj.sys.dao.SysRoleMenuDao">
    <!--写入角色和菜单关系数据-->
    <insert id="insertRoleMenus">
        insert into
        sys_role_menus(role_id,menu_id)
        values <!--(1,2),(1,3),(1,4)-->
        <foreach collection="menuIds" separator="," item="menuId">
            (#{roleId},#{menuId})
        </foreach>
    </insert>
</mapper>

Service层

  • 接口规范定义
    • 通过原型设计找到项目需要完成的业务,来进行业务层的规范定义
      ```java package com.cy.pj.sys.service;

/**

  • 定义角色业务规范 / public interface SysRoleService { /*

    • 基于条件查询角色信息
    • @param entity 封装了查询条件的对象
    • @return */ List findRoles(SysRole entity);

      /**

    • 添加角色
    • @param entity 封装了角色信息的对象
    • @return 受影响的行数 */ int saveRole(SysRole entity);

      /**

    • 基于角色id查询角色以及角色对应菜单关系数据,将数据呈现出来用于更新
    • @param id
    • @return */ SysRole findById(Integer id);

      /**

    • 基于角色id更新角色以及角色对应的菜单关系数据
    • @param entity
    • @return */ int updateRole(SysRole entity);

      /**

    • 为用户授权时,查询可授权的角色
    • @return */ List findCheckRoles(); } ```
  • 接口实现
    • 在实际业务中,一些操作要么都执行,要么不执行,就需要事务控制
    • 在更新角色时,角色菜单关系(一对多)数据的更新一般通过先删除原有关系后添加关系来完成 ```java package com.cy.pj.sys.service.impl;

@Service public class SysRoleServiceImpl implements SysRoleService { /关联角色表dao对象*/ @Autowired private SysRoleDao sysRoleDao; /关联角色菜单关系表dao对象*/ @Autowired private SysRoleMenuDao sysRoleMenuDao;

@Override
public List<SysRole> findRoles(SysRole entity) {
    return sysRoleDao.selectRoles(entity);
}
/**
 * 保存角色以及角色菜单关系数据(思考如何保证数据的完整性)
 * @param entity 封装了要新增的角色信息
 * @return
 */
@Override
public int saveRole(SysRole entity) {
    //保存角色自身信息
    int rows = sysRoleDao.insertRole(entity);
    //保存角色菜单关系数据
    sysRoleMenuDao.insertRoleMenus(entity.getId(), entity.getMenuIds());
    return rows;
}

@Override
public SysRole findById(Integer id) {
    return sysRoleDao.selectById(id);
}

@Override
public int updateRole(SysRole entity) {
    //更新角色自身信息
    int rows = sysRoleDao.updateRole(entity);
    if (rows==0){
        throw new ServiceException("记录可能已经不存在了");
    }
    //更新角色菜单关系数据(one to many数据更新一般是先删除原有关系,再添加新的关系)
    sysRoleMenuDao.deleteByRoleId(entity.getId());
    sysRoleMenuDao.insertRoleMenus(entity.getId(), entity.getMenuIds());
    return rows;
}

@Override
public List<CheckBox> findCheckRoles() {
    return sysRoleDao.selectCheckRoles();
}

}

<a name="rNxyx"></a>
### Controller层
```java
package com.cy.pj.sys.web.controller;

@RequestMapping("/role/")
@RestController
public class SysRoleController {
    @Autowired
    private SysRoleService sysRoleService;

    @GetMapping
    public JsonResult doFindRoles(SysRole entity) {
        return new JsonResult(PageUtil.startPage().doSelectPageInfo(()->{
            sysRoleService.findRoles(entity);
        }));
    }

    @PostMapping
    public JsonResult doSaveRole(@RequestBody SysRole entity){
        sysRoleService.saveRole(entity);
        return new JsonResult("save ok");
    }

    @GetMapping("{id}")
    public JsonResult doFindById(@PathVariable Integer id){
        return new JsonResult(sysRoleService.findById(id));
    }

    @PutMapping
    public JsonResult doUpdateRole(@RequestBody SysRole entity){
        sysRoleService.updateRole(entity);
        return new JsonResult("update ok");
    }

    @GetMapping("checkRoles")
    public JsonResult doFindCheckRoles(){
        return new JsonResult(sysRoleService.findCheckRoles());
    }
}

Main

package com.cy;

@EnableCaching //启动springboot工程中内置缓存
@SpringBootApplication
public class AdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminApplication.class,args);
    }
}