业务描述

  • 权限管理子系统设计中都会有一个用户管理的模块,对注册的用户进行统一管理,不同的用户通过授予不同的角色来进行权限管理

    系统设计

    原型设计

  • 用户列表页面

image.png

  • 用户修改页面

image.png

  • 用户添加页面选择部门

image.png

表设计

  • common模块中

    核心API设计

    image.png

    逻辑实现

    领域对象POJO

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

import lombok.Data; import java.io.Serializable; import java.util.Date; import java.util.List; /用户对象设计及实现*/ @Data public class SysUser implements Serializable { private static final long serialVersionUID = 6030354920933251109L; private Integer id; private String username; private String password; private String salt; private String mobile; private String email; private Integer valid=1;//默认为有效状态,0 代表无效 private Integer deptId; private String deptName; /用户拥有的角色*/ private List roleIds; private Date createdTime; 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. /**定义SysUserDao,负责用户数据访问逻辑规范的定义*/
  7. @Mapper
  8. public interface SysUserDao {
  9. /**
  10. * 分页查询用户以及用户对应部门相关信息
  11. * @param entity 封装了查询条件的对象
  12. * @return 查询到的用户信息,表中的一行记录映射为内存中一个SysUser对象
  13. */
  14. List<SysUser> selectUsers(SysUser entity);
  15. /**
  16. * 禁用启用操作
  17. * @param id
  18. * @param valid
  19. * @param modifiedUser
  20. * @return
  21. */
  22. @Update("update sys_users set valid=#{valid},modifiedTime=now(),modifiedUser=#{modifiedUser} where id=#{id}")
  23. int validById(Integer id,Integer valid,String modifiedUser);
  24. /**
  25. * 保存用户自身信息(用户信息中密码要求是已加密的密码)
  26. * @param entity
  27. * @return
  28. */
  29. int insertUser(SysUser entity);
  30. /**
  31. * 更新用户自身信息(这里的更新不更新密码)
  32. * @param entity
  33. * @return
  34. */
  35. int updateUser(SysUser entity);
  36. /**
  37. * 基于id查询用户信息,修改用户信息时使用
  38. * @param id
  39. * @return
  40. */
  41. SysUser selectById(Integer id);
  42. /**
  43. * 基于用户名查询用户信息(登录时使用)
  44. * @param username
  45. * @return
  46. */
  47. @Select("select * from sys_users where username=#{username}")
  48. SysUser selectUserByUsername(String username);
  49. }
<?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.SysUserDao">
    <!--<resultMap id="sysUser" type="com.cy.pj.sys.pojo.SysUser">
        <result property="deptName" column="name"></result>
    </resultMap>-->
    <select id="selectUsers" resultType="com.cy.pj.sys.pojo.SysUser">
        select su.*,sd.name deptName
        from sys_users su
        left join sys_depts sd
        on su.deptId = sd.id
        <where>
            <if test="username!=null and username!=''">
                username like concat("%",#{username},"%")
            </if>
        </where>
         order by createdTime desc
    </select>
    <insert id="insertUser" parameterType="com.cy.pj.sys.pojo.SysUser" useGeneratedKeys="true" keyProperty="id">
        insert into sys_users
        (username,password,salt,mobile,email,deptId,valid,
        createdTime,modifiedTime,createdUser,modifiedUser)
        values
        (#{username},#{password},#{salt},#{mobile},#{email},#{deptId},#{valid},
        now(),now(),#{createdUser},#{modifiedUser})
    </insert>
    <update id="updateUser" parameterType="com.cy.pj.sys.pojo.SysUser">
        update sys_users
        set username=#{username},
        deptId=#{deptId},
        mobile=#{mobile},
        email=#{email},
        modifiedTime=now(),
        modifiedUser=#{modifiedUser}
        where id=#{id}
    </update>

    <select id="selectById" resultType="com.cy.pj.sys.pojo.SysUser">
        select u.*,d.name deptName
        from sys_users u
        left join sys_depts d
        on u.deptId=d.id
        where u.id=#{id}
    </select>
</mapper>
  • 用户角色关系数据 ```java package com.cy.pj.sys.dao;

@Mapper public interface SysUserRoleDao { /**

 * 新增用户和角色关系数据
 * @param userId
 * @param roleIds
 * @return
 */
int insertUserRoles(Integer userId, List<Integer> roleIds);

/**
 * 基于用户id删除用户和角色关系数据
 * @param userId
 * @return
 */
@Delete("delete from sys_user_roles where user_id=#{userId}")
int deleteByUserId(Integer userId);

/**
 * 基于用户id查询角色id,在查询用户以及用户对应的角色id时使用
 * @param userId
 * @return
 */
@Select("select role_id from sys_user_roles where user_id = #{userId}")
List<Integer> selectRoleIdsByUserId(Integer userId);

}

```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.SysUserRoleDao">
    <insert id="insertUserRoles" >
        insert into sys_user_roles
        (user_id,role_id)
        values
        <foreach collection="roleIds" separator="," item="roleId">
            (#{userId},#{roleId})
        </foreach>
    </insert>
</mapper>

Service层

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

import com.cy.pj.sys.pojo.SysUser;

import java.util.List;

public interface SysUserService { List findUsers(SysUser entity);

SysUser findById(Integer id);

/**
 * 添加新的用户信息以及用户和角色关系数据
 * @param entity
 * @return
 */
int saveUser(SysUser entity);

/**
 *
 * @param entity
 * @return
 */
int updateUser(SysUser entity);

/**
 * 基于用户id修改用户状态(禁用,启用)
 * @param id 用户id
 * @param valid 用户状态
 * @return
 */
int validById(Integer id,Integer valid);

}


- 接口实现
   - 在实际业务中,一些操作要么都执行,要么不执行,就需要事务控制
   - 在更新角色时,角色菜单关系(一对多)数据的更新一般通过先删除原有关系后添加关系来完成
```java
package com.cy.pj.sys.service.impl;

@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private SysUserRoleDao sysUserRoleDao;

    @Override
    public List<SysUser> findUsers(SysUser entity) {
        /*return PageUtil.startPage().doSelectPageInfo(()->{
          sysUserDao.selectUsers(entity);
        });*/
        return sysUserDao.selectUsers(entity);
    }

    @Override
    public SysUser findById(Integer id) {
        //查询用户以及用户对应的部门信息
        SysUser user = sysUserDao.selectById(id);
        if (user==null)
            throw new ServiceException("没有找到对应的用户");
        //查询用户对应的角色信息
        List<Integer> roleIds = sysUserRoleDao.selectRoleIdsByUserId(id);
        //将查询到的角色id封装到user对象
        user.setRoleIds(roleIds);
        return user;
    }

    @Override
    public int saveUser(SysUser entity) {
        //1.保存用户自身信息
        //1.1对参数校验
        //1.2对密码进行加密(MD5盐值加密(不可逆,相同内容加密结果也相同))
        String password = entity.getPassword();
        //获得随机盐值(随机字符串)
        String salt = UUID.randomUUID().toString();
        //设置加密规则,加密算法,加密源,盐,加密次数  借助shiro框架中的api对密码进行md5加密
        SimpleHash simpleHash = new SimpleHash("MD5", password, salt, 1);
        //将加密结果转换为16进制字符串(建议)
        password = simpleHash.toHex();
        entity.setSalt(salt);
        entity.setPassword(password);
        //1.3将用户信息持久化到数据库
        int rows = sysUserDao.insertUser(entity);
        //保存用户和角色关系数据
        sysUserRoleDao.insertUserRoles(entity.getId(), entity.getRoleIds());
        return rows;
    }

    @Override
    public int updateUser(SysUser entity) {
        //1.更新用户自身信息
        int rows = sysUserDao.updateUser(entity);
        if (rows==0)
            throw new ServiceException("记录可能不存在");
        //2.更新用户和角色关系数据
        //2.1删除原有的关系数据
        sysUserRoleDao.deleteByUserId(entity.getId());
        //2.2添加新的关系数据
        sysUserRoleDao.insertUserRoles(entity.getId(), entity.getRoleIds());
        return rows;
    }

    @Override
    public int validById(Integer id, Integer valid) {
        String username = ((SysUser)SecurityUtils.getSubject().getPrincipal()).getUsername();
        int rows = sysUserDao.validById(id, valid,username);
        if (rows==0){
            throw new ServiceException("记录可能不存在了");
        }
        return rows;
    }
}

Controller层

package com.cy.pj.sys.web.controller;

import com.cy.pj.common.annotation.RequiredLog;
import com.cy.pj.common.pojo.JsonResult;
import com.cy.pj.common.util.PageUtil;
import com.cy.pj.sys.pojo.SysUser;
import com.cy.pj.sys.service.SysUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@CrossOrigin
@RequestMapping("/user/")
@RestController
public class SysUserController {
    @Autowired
    private SysUserService sysUserService;

    @GetMapping("login/{username}/{password}")
    public JsonResult doLogin(@PathVariable String username,@PathVariable String password){
        System.out.println(username);
        //获取Shiro中的Subject对象,基于此对象提交用户信息
        Subject subject = SecurityUtils.getSubject();
        //执行登录(将用户名和密码提交给securityManager)
        UsernamePasswordToken token = new UsernamePasswordToken();
        token.setUsername(username);
        token.setPassword(password.toCharArray());
        token.setRememberMe(true);
        subject.login(token);
        return new JsonResult("login ok");
    }

    //@RequiredLog(operation = "查询用户信息")
    //@RequiresPermissions("sys:user:view")
    @GetMapping
    public JsonResult doFindUsers(SysUser entity){
        return new JsonResult(PageUtil.startPage().doSelectPageInfo(()->{
            sysUserService.findUsers(entity);
        }));
    }

    @PostMapping
    public JsonResult doSaveUser(@RequestBody SysUser entity){
        sysUserService.saveUser(entity);
        return new JsonResult("save ok");
    }

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

    @PutMapping
    public JsonResult doUpdateUser(@RequestBody SysUser entity){
        sysUserService.updateUser(entity);
        return new JsonResult("update ok");
    }

    //@RequiresPermissions("sys:user:update")
    @PatchMapping("{id}/{valid}") //一部分数据的更新可使用Patch请求,当然也可使用Put
    public JsonResult doValidById(@PathVariable Integer id,@PathVariable Integer valid){
        sysUserService.validById(id, valid);
        return new JsonResult("update valid success");
    }
}