spring cloud(六)系統管理之用戶、角色、菜單數據庫設計及實現

本系列文章均參考:朝雨憶輕塵,感謝博主!

這裏還有他的技術交流羣:429854222,歡迎大家支持博主

若有侵權,還請告知,一定刪除

一、需求說明

不同的賬戶登錄系統看到的是不同的菜單,最高權限賬戶能看到所有的。

二、數據庫設計

首先看張ER圖:

我們看圖說話:後臺人員各自擁有不同的賬戶,分配了不同的角色,一個賬號可以分配多個角色(一對多),一個角色也可以分配給不同的賬戶(一對多),所以賬戶角色是多對多的關係;同理。角色權限也是多對多,這裏設計的時候把菜單和權限綁定在一起。

數據庫設計如下:

賬戶表sys_user:

角色表sys_role:

菜單表sys_menu:

用戶角色表sys_user_role:

角色菜單表sys_role_menu:

 

這樣的話,根據需求的數據庫就設計出來了,接下來就是代碼實現了。

三、代碼實現

3.1、用戶

3.1.1、model

public class SysUser extends BaseModel {

    private String name;

    private String password;

    private String salt;

    private String email;

    private String mobile;

    private Byte status;

    private Long deptId;
    
    private String deptName;
    
    private Byte delFlag;
    
    private String roleNames;
    
    private List<SysUserRole> userRoles = new ArrayList<>();

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getSalt() {
		return salt;
	}

	public void setSalt(String salt) {
		this.salt = salt;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getMobile() {
		return mobile;
	}

	public void setMobile(String mobile) {
		this.mobile = mobile;
	}

	public Byte getStatus() {
		return status;
	}

	public void setStatus(Byte status) {
		this.status = status;
	}

	public Long getDeptId() {
		return deptId;
	}

	public void setDeptId(Long deptId) {
		this.deptId = deptId;
	}

	public String getDeptName() {
		return deptName;
	}

	public void setDeptName(String deptName) {
		this.deptName = deptName;
	}

	public Byte getDelFlag() {
		return delFlag;
	}

	public void setDelFlag(Byte delFlag) {
		this.delFlag = delFlag;
	}

	public String getRoleNames() {
		return roleNames;
	}

	public void setRoleNames(String roleNames) {
		this.roleNames = roleNames;
	}

	public List<SysUserRole> getUserRoles() {
		return userRoles;
	}

	public void setUserRoles(List<SysUserRole> userRoles) {
		this.userRoles = userRoles;
	}

}

3.1.2、dao

public interface SysUserMapper {
    int deleteByPrimaryKey(Long id);

    int insert(SysUser record);

    int insertSelective(SysUser record);

    SysUser selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(SysUser record);

    int updateByPrimaryKey(SysUser record);
    
    List<SysUser> findPage();
    
    SysUser findByName(@Param(value="name") String name);
    
	List<SysUser> findPageByName(@Param(value="name") String name);
	
	List<SysUser> findPageByNameAndEmail(@Param(value="name") String name, @Param(value="email") String email);
}

3.1.3、mapper

<?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.***.dao.SysUserMapper">
  <resultMap id="BaseResultMap" type="com.***.model.SysUser">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="password" jdbcType="VARCHAR" property="password" />
    <result column="salt" jdbcType="VARCHAR" property="salt" />
    <result column="email" jdbcType="VARCHAR" property="email" />
    <result column="mobile" jdbcType="VARCHAR" property="mobile" />
    <result column="status" jdbcType="TINYINT" property="status" />
    <result column="dept_id" jdbcType="BIGINT" property="deptId" />
    <result column="create_by" jdbcType="BIGINT" property="createBy" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="last_update_by" jdbcType="BIGINT" property="lastUpdateBy" />
    <result column="last_update_time" jdbcType="TIMESTAMP" property="lastUpdateTime" />
    <result column="del_flag" jdbcType="TINYINT" property="delFlag" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name, password, salt, email, mobile, status, dept_id, create_by, create_time, 
    last_update_by, last_update_time, del_flag
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_user
    where id = #{id,jdbcType=BIGINT}  
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    delete from sys_user
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.***.model.SysUser">
    insert into sys_user (id, name, password, 
      salt, email, mobile, 
      status, dept_id, create_by, 
      create_time, last_update_by, last_update_time, 
      del_flag)
    values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, 
      #{salt,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{mobile,jdbcType=VARCHAR}, 
      #{status,jdbcType=TINYINT}, #{deptId,jdbcType=BIGINT}, #{createBy,jdbcType=BIGINT}, 
      #{createTime,jdbcType=TIMESTAMP}, #{lastUpdateBy,jdbcType=BIGINT}, #{lastUpdateTime,jdbcType=TIMESTAMP}, 
      #{delFlag,jdbcType=TINYINT})
  </insert>
  <insert id="insertSelective" parameterType="com.***.model.SysUser">
    insert into sys_user
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="password != null">
        password,
      </if>
      <if test="salt != null">
        salt,
      </if>
      <if test="email != null">
        email,
      </if>
      <if test="mobile != null">
        mobile,
      </if>
      <if test="status != null">
        status,
      </if>
      <if test="deptId != null">
        dept_id,
      </if>
      <if test="createBy != null">
        create_by,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="lastUpdateBy != null">
        last_update_by,
      </if>
      <if test="lastUpdateTime != null">
        last_update_time,
      </if>
      <if test="delFlag != null">
        del_flag,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        #{password,jdbcType=VARCHAR},
      </if>
      <if test="salt != null">
        #{salt,jdbcType=VARCHAR},
      </if>
      <if test="email != null">
        #{email,jdbcType=VARCHAR},
      </if>
      <if test="mobile != null">
        #{mobile,jdbcType=VARCHAR},
      </if>
      <if test="status != null">
        #{status,jdbcType=TINYINT},
      </if>
      <if test="deptId != null">
        #{deptId,jdbcType=BIGINT},
      </if>
      <if test="createBy != null">
        #{createBy,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="lastUpdateBy != null">
        #{lastUpdateBy,jdbcType=BIGINT},
      </if>
      <if test="lastUpdateTime != null">
        #{lastUpdateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="delFlag != null">
        #{delFlag,jdbcType=TINYINT},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.***.model.SysUser">
    update sys_user
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        password = #{password,jdbcType=VARCHAR},
      </if>
      <if test="salt != null">
        salt = #{salt,jdbcType=VARCHAR},
      </if>
      <if test="email != null">
        email = #{email,jdbcType=VARCHAR},
      </if>
      <if test="mobile != null">
        mobile = #{mobile,jdbcType=VARCHAR},
      </if>
      <if test="status != null">
        status = #{status,jdbcType=TINYINT},
      </if>
      <if test="deptId != null">
        dept_id = #{deptId,jdbcType=BIGINT},
      </if>
      <if test="createBy != null">
        create_by = #{createBy,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="lastUpdateBy != null">
        last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
      </if>
      <if test="lastUpdateTime != null">
        last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="delFlag != null">
        del_flag = #{delFlag,jdbcType=TINYINT},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.***.model.SysUser">
    update sys_user
    set name = #{name,jdbcType=VARCHAR},
      password = #{password,jdbcType=VARCHAR},
      salt = #{salt,jdbcType=VARCHAR},
      email = #{email,jdbcType=VARCHAR},
      mobile = #{mobile,jdbcType=VARCHAR},
      status = #{status,jdbcType=TINYINT},
      dept_id = #{deptId,jdbcType=BIGINT},
      create_by = #{createBy,jdbcType=BIGINT},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
      last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
      del_flag = #{delFlag,jdbcType=TINYINT}
    where id = #{id,jdbcType=BIGINT}
  </update>
  <select id="findPage" resultMap="BaseResultMap">
    select u.*, (select d.name from sys_dept d where d.id = u.dept_id) deptName from sys_user u where 
  </select>
  <select id="findByName" parameterType="java.lang.String" resultMap="BaseResultMap">
    select u.*, (select d.name from sys_dept d where d.id = u.dept_id) deptName from sys_user u
    where u.name = #{name,jdbcType=VARCHAR}
  </select>
  <select id="findPageByName" parameterType="java.lang.String" resultMap="BaseResultMap">
  	<bind name="pattern" value="'%' + _parameter.name + '%'" />
    select u.*, (select d.name from sys_dept d where d.id = u.dept_id) deptName from sys_user u
    where u.name like #{pattern} 
  </select>
  <select id="findPageByNameAndEmail" parameterType="java.lang.String" resultMap="BaseResultMap">
  	<bind name="patternName" value="'%' + _parameter.name + '%'" />
  	<bind name="patternEmail" value="'%' + _parameter.email + '%'" />
    select u.*, (select d.name from sys_dept d where d.id = u.dept_id) deptName from sys_user u
    where u.name like #{patternName}
    and u.email like #{patternEmail} 
  </select>
</mapper>

3.1.4、service以及impl

public interface SysUserService extends CurdService<SysUser> {

	SysUser findByName(String username);
	
	SysUser findByToken(String token);

	/**
	 * 查找用戶的菜單權限標識集合
	 * @param userName
	 * @return
	 */
	Set<String> findPermissions(String userName);

	/**
	 * 查找用戶的角色集合
	 * @param userName
	 * @return
	 */
	List<SysUserRole> findUserRoles(Long userId);
	
	int savePWD(SysUser sysUser);

}
@Service
public class SysUserServiceImpl  implements SysUserService {

	@Autowired
	private SysUserMapper sysUserMapper;
	@Autowired
	private SysMenuMapper sysMenuMapper;
	@Autowired
	private SysUserRoleMapper sysUserRoleMapper;
	@Autowired
	private SysRoleMapper sysRoleMapper;
	@Autowired
	private SysUserTokenMapper sysUserTokenMapper;

	@Override
	public int save(SysUser record) {
		Long id = null;
		if(record.getId() == null || record.getId() == 0) {
			// 新增用戶
			sysUserMapper.insertSelective(record);
			id = record.getId();
		} else {
			// 更新用戶信息
			sysUserMapper.updateByPrimaryKeySelective(record);
		}
		// 更新用戶角色
		if(id != null && id == 0) {
			return 1;
		}
		if(id != null) {
			for(SysUserRole sysUserRole:record.getUserRoles()) {
				sysUserRole.setUserId(id);
			}
		} else {
			sysUserRoleMapper.deleteByUserId(record.getId());
		}
		for(SysUserRole sysUserRole:record.getUserRoles()) {
			sysUserRoleMapper.insertSelective(sysUserRole);
		}
		return 1;
	}
	
	@Override
	public int savePWD(SysUser sysUser) {
		if(sysUser.getId() == null || sysUser.getId() == 0) {
			return 0;
		}
		// 更新用戶信息
		return sysUserMapper.updateByPrimaryKeySelective(sysUser);
	}

	@Override
	public int delete(SysUser record) {
		return sysUserMapper.deleteByPrimaryKey(record.getId());
	}

	@Override
	public int delete(List<SysUser> records) {
		for(SysUser record:records) {
			delete(record);
		}
		return 1;
	}

	@Override
	public SysUser findById(Long id) {
		return sysUserMapper.selectByPrimaryKey(id);
	}
	
	@Override
	public SysUser findByName(String name) {
		return sysUserMapper.findByName(name);
	}
	
	@Override
	public PageResult findPage(PageRequest pageRequest) {
		PageResult pageResult = null;
		String name = getColumnFilterValue(pageRequest, "name");
		String email = getColumnFilterValue(pageRequest, "email");
		if(name != null) {
			if(email != null) {
				pageResult = MybatisPageHelper.findPage(pageRequest, sysUserMapper, "findPageByNameAndEmail", name, email);
			} else {
				pageResult = MybatisPageHelper.findPage(pageRequest, sysUserMapper, "findPageByName", name);
			}
		} else {
			pageResult = MybatisPageHelper.findPage(pageRequest, sysUserMapper);
		}
		// 加載用戶角色信息
		findUserRoles(pageResult);
		return pageResult;
	}

	/**
	 * 獲取過濾字段的值
	 * @param filterName
	 * @return
	 */
	public String getColumnFilterValue(PageRequest pageRequest, String filterName) {
		String value = null;
		ColumnFilter columnFilter = pageRequest.getColumnFilter(filterName);
		if(columnFilter != null) {
			value = columnFilter.getValue();
		}
		return value;
	}
	
	/**
	 * 加載用戶角色
	 * @param pageResult
	 */
	private void findUserRoles(PageResult pageResult) {
		List<?> content = pageResult.getContent();
		for(Object object:content) {
			SysUser sysUser = (SysUser) object;
			List<SysUserRole> userRoles = findUserRoles(sysUser.getId());
			sysUser.setUserRoles(userRoles);
			sysUser.setRoleNames(getRoleNames(userRoles));
		}
	}

	private String getRoleNames(List<SysUserRole> userRoles) {
		StringBuilder sb = new StringBuilder();
		for(Iterator<SysUserRole> iter=userRoles.iterator(); iter.hasNext();) {
			SysUserRole userRole = iter.next();
			SysRole sysRole = sysRoleMapper.selectByPrimaryKey(userRole.getRoleId());
			if(sysRole == null) {
				continue ;
			}
			sb.append(sysRole.getRemark());
			if(iter.hasNext()) {
				sb.append(", ");
			}
		}
		return sb.toString();
	}

	@Override
	public Set<String> findPermissions(String userName) {	
		Set<String> perms = new HashSet<>();
		List<SysMenu> sysMenus = findByUser(userName);
		for(SysMenu sysMenu:sysMenus) {
			if(sysMenu.getPerms() != null && !"".equals(sysMenu.getPerms())) {
				perms.add(sysMenu.getPerms());
			}
		}
		return perms;
	}

	@Override
	public List<SysUserRole> findUserRoles(Long userId) {
		return sysUserRoleMapper.findUserRoles(userId);
	}
	
	private List<SysMenu> findByUser(String userName) {
		if(userName == null || "".equals(userName) || SysConstants.ADMIN.equalsIgnoreCase(userName)) {
			return sysMenuMapper.findAll();
		}
		return sysMenuMapper.findByUserName(userName);
	}

	@Override
	public SysUser findByToken(String token) {
		SysUserToken sysUserToken = sysUserTokenMapper.findByToken(token);
		return sysUserMapper.selectByPrimaryKey(sysUserToken.getUserId());
	}

}

代碼有的地方是跟token有關的,這是因爲後臺API的接口都是通過token鑑權來訪問的(每個用戶登錄一次都會生成一個token),通過token來查詢更方便一點。

重點方法:findPermissionsfindUserRoles

3.2、角色

3.2.1、model

public class SysRole extends BaseModel {

    private String name;

    private String remark;

    private Byte delFlag;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public Byte getDelFlag() {
		return delFlag;
	}

	public void setDelFlag(Byte delFlag) {
		this.delFlag = delFlag;
	}

}

3.2.2、dao

public interface SysRoleMapper {
    int deleteByPrimaryKey(Long id);

    int insert(SysRole record);

    int insertSelective(SysRole record);

    SysRole selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(SysRole record);

    int updateByPrimaryKey(SysRole record);
    
    List<SysRole> findPage();

	List<SysRole> findAll();
	
	List<SysRole> findPageByName(@Param(value="name") String name);
	
	List<SysRole> findByName(@Param(value="name") String name);
}

3.2.3、mapper

<?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.***.dao.SysRoleMapper">
  <resultMap id="BaseResultMap" type="com.***.model.SysRole">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="remark" jdbcType="VARCHAR" property="remark" />
    <result column="create_by" jdbcType="BIGINT" property="createBy" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="last_update_by" jdbcType="BIGINT" property="lastUpdateBy" />
    <result column="last_update_time" jdbcType="TIMESTAMP" property="lastUpdateTime" />
    <result column="del_flag" jdbcType="TINYINT" property="delFlag" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name, remark, create_by, create_time, last_update_by, last_update_time, 
    del_flag
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_role
    where id = #{id,jdbcType=BIGINT} 
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    delete from sys_role
    where id = #{id,jdbcType=BIGINT} 
  </delete>
  <insert id="insert" parameterType="com.***.model.SysRole">
    insert into sys_role (id, name, remark, 
      create_by, create_time, last_update_by, 
      last_update_time, del_flag)
    values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR}, 
      #{createBy,jdbcType=BIGINT}, #{createTime,jdbcType=TIMESTAMP}, #{lastUpdateBy,jdbcType=BIGINT}, 
      #{lastUpdateTime,jdbcType=TIMESTAMP}, #{delFlag,jdbcType=TINYINT})
  </insert>
  <insert id="insertSelective" parameterType="com.***.model.SysRole">
    insert into sys_role
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="remark != null">
        remark,
      </if>
      <if test="createBy != null">
        create_by,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="lastUpdateBy != null">
        last_update_by,
      </if>
      <if test="lastUpdateTime != null">
        last_update_time,
      </if>
      <if test="delFlag != null">
        del_flag,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="remark != null">
        #{remark,jdbcType=VARCHAR},
      </if>
      <if test="createBy != null">
        #{createBy,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="lastUpdateBy != null">
        #{lastUpdateBy,jdbcType=BIGINT},
      </if>
      <if test="lastUpdateTime != null">
        #{lastUpdateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="delFlag != null">
        #{delFlag,jdbcType=TINYINT},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.***.model.SysRole">
    update sys_role
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="remark != null">
        remark = #{remark,jdbcType=VARCHAR},
      </if>
      <if test="createBy != null">
        create_by = #{createBy,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="lastUpdateBy != null">
        last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
      </if>
      <if test="lastUpdateTime != null">
        last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="delFlag != null">
        del_flag = #{delFlag,jdbcType=TINYINT},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.***.model.SysRole">
    update sys_role
    set name = #{name,jdbcType=VARCHAR},
      remark = #{remark,jdbcType=VARCHAR},
      create_by = #{createBy,jdbcType=BIGINT},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
      last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
      del_flag = #{delFlag,jdbcType=TINYINT}
    where id = #{id,jdbcType=BIGINT}
  </update>
  <select id="findPage" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_role  
  </select>
  <select id="findAll" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_role  
  </select>
  <select id="findPageByName" parameterType="java.lang.String" resultMap="BaseResultMap">
  	<bind name="pattern" value="'%' + _parameter.name + '%'" />
  	select 
    <include refid="Base_Column_List" />
    from sys_role
    where name like #{pattern} 
  </select>
  <select id="findByName" parameterType="java.lang.String" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_role
    where name = #{name,jdbcType=VARCHAR} 
  </select>
</mapper>

3.2.4、service以及impl

public interface SysRoleService extends CurdService<SysRole> {

	/**
	 * 查詢全部
	 * @return
	 */
	List<SysRole> findAll();

	/**
	 * 查詢角色菜單集合
	 * @return
	 */
	List<SysMenu> findRoleMenus(Long roleId);

	/**
	 * 保存角色菜單
	 * @param records
	 * @return
	 */
	int saveRoleMenus(List<SysRoleMenu> records);

	/**
	 * 根據名稱查詢
	 * @param name
	 * @return
	 */
	List<SysRole> findByName(String name);
	
	
	/**
	 * 查詢角色區域集合
	 * @return
	 */
	List<SysArea> findRoleAreas(Long roleId);

	/**
	 * 保存角色區域
	 * @param records
	 * @return
	 */
	int saveRoleAreas(List<SysRoleArea> records);

	List<SysRole> findRoleByName(String name);
}
@Service
public class SysRoleServiceImpl  implements SysRoleService {

	@Autowired
	private SysRoleMapper sysRoleMapper;
	@Autowired
	private SysRoleMenuMapper sysRoleMenuMapper;
	@Autowired
	private SysRoleAreaMapper sysRoleAreaMapper;
	@Autowired
	private SysMenuMapper sysMenuMapper;
	@Autowired
	private SysAreaMapper sysAreaMapper;
	@Autowired
	private SysUserMapper sysUserMapper;
	@Autowired
	private SysUserRoleMapper sysUserRoleMapper;

	@Override
	public int save(SysRole record) {
		if(record.getId() == null || record.getId() == 0) {
			return sysRoleMapper.insertSelective(record);
		}
		return sysRoleMapper.updateByPrimaryKeySelective(record);
	}

	@Override
	public int delete(SysRole record) {
		return sysRoleMapper.deleteByPrimaryKey(record.getId());
	}

	@Override
	public int delete(List<SysRole> records) {
		for(SysRole record:records) {
			delete(record);
		}
		return 1;
	}

	@Override
	public SysRole findById(Long id) {
		return sysRoleMapper.selectByPrimaryKey(id);
	}

	@Override
	public PageResult findPage(PageRequest pageRequest) {
		ColumnFilter columnFilter = pageRequest.getColumnFilter("name");
		if(columnFilter != null && columnFilter.getValue() != null) {
			return MybatisPageHelper.findPage(pageRequest, sysRoleMapper, "findPageByName", columnFilter.getValue());
		}
		return MybatisPageHelper.findPage(pageRequest, sysRoleMapper);
	}

	@Override
	public List<SysRole> findAll() {
		return sysRoleMapper.findAll();
	}

	public SysRoleMapper getSysRoleMapper() {
		return sysRoleMapper;
	}

	public void setSysRoleMapper(SysRoleMapper sysRoleMapper) {
		this.sysRoleMapper = sysRoleMapper;
	}

	@Override
	public List<SysMenu> findRoleMenus(Long roleId) {
		SysRole sysRole = sysRoleMapper.selectByPrimaryKey(roleId);
		if(SysConstants.ADMIN.equalsIgnoreCase(sysRole.getName())) {
			// 如果是超級管理員,返回全部
			return sysMenuMapper.findAll();
		}
		return sysMenuMapper.findRoleMenus(roleId);
	}

	@Transactional
	@Override
	public int saveRoleMenus(List<SysRoleMenu> records) {
		if(records == null || records.isEmpty()) {
			return 1;
		}
		Long roleId = records.get(0).getRoleId(); 
		sysRoleMenuMapper.deleteByRoleId(roleId);
		for(SysRoleMenu record:records) {
			sysRoleMenuMapper.insertSelective(record);
		}
		return 1;
	}

	@Override
	public List<SysRole> findByName(String name) {
		return sysRoleMapper.findByName(name);
	}

	@Override
	public List<SysArea> findRoleAreas(Long roleId) {
		SysRole sysRole = sysRoleMapper.selectByPrimaryKey(roleId);
		if(SysConstants.ADMIN.equalsIgnoreCase(sysRole.getName())) {
			// 如果是超級管理員,返回全部
			return sysAreaMapper.findAll();
		}
		return sysAreaMapper.findRoleAreas(roleId);
	}

	@Override
	public int saveRoleAreas(List<SysRoleArea> records) {
		if(records == null || records.isEmpty()) {
			return 1;
		}
		Long roleId = records.get(0).getRoleId(); 
		sysRoleAreaMapper.deleteByRoleId(roleId);
		for(SysRoleArea record:records) {
			sysRoleAreaMapper.insert(record);
		}
		return 1;
	}

	@Override
	public List<SysRole> findRoleByName(String name) {
		SysUser user = sysUserMapper.findByName(name);
		List<SysUserRole> userRoles = sysUserRoleMapper.findUserRoles(user.getId());
		List<SysRole> res = new ArrayList<>();
		for (SysUserRole userRole : userRoles) {
			res.add(sysRoleMapper.selectByPrimaryKey(userRole.getRoleId()));
		}
		return res;
	}

}

重點方法: findRoleMenus、saveRoleMenus、findRoleByName

3.3、菜單

3.3.1、model

public class SysMenu extends BaseModel {

    private Long parentId;

    private String name;

    private String url;

    private String perms;

    private Integer type;

    private String icon;

    private Integer orderNum;

    private Byte delFlag;

    // 非數據庫字段
    private String parentName;
    // 非數據庫字段
    private Integer level;
    // 非數據庫字段
    private List<SysMenu> children;
    
	public Long getParentId() {
		return parentId;
	}

	public void setParentId(Long parentId) {
		this.parentId = parentId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getPerms() {
		return perms;
	}

	public void setPerms(String perms) {
		this.perms = perms;
	}

	public Integer getType() {
		return type;
	}

	public void setType(Integer type) {
		this.type = type;
	}

	public String getIcon() {
		return icon;
	}

	public void setIcon(String icon) {
		this.icon = icon;
	}

	public Integer getOrderNum() {
		return orderNum;
	}

	public void setOrderNum(Integer orderNum) {
		this.orderNum = orderNum;
	}

	public Byte getDelFlag() {
		return delFlag;
	}

	public void setDelFlag(Byte delFlag) {
		this.delFlag = delFlag;
	}

	public List<SysMenu> getChildren() {
		return children;
	}

	public void setChildren(List<SysMenu> children) {
		this.children = children;
	}

	public Integer getLevel() {
		return level;
	}

	public void setLevel(Integer level) {
		this.level = level;
	}

	public String getParentName() {
		return parentName;
	}

	public void setParentName(String parentName) {
		this.parentName = parentName;
	}
	
}

3.3.2、dao

public interface SysMenuMapper {
    int deleteByPrimaryKey(Long id);

    int insert(SysMenu record);

    int insertSelective(SysMenu record);

    SysMenu selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(SysMenu record);

    int updateByPrimaryKey(SysMenu record);
    
	List<SysMenu> findPage();

	List<SysMenu> findPageByName(@Param(value="name") String name);
	
	List<SysMenu> findAll();

	List<SysMenu> findByUserName(@Param(value="userName") String userName);
	
	List<SysMenu> findByName(@Param(value="name") String name);
	
	List<SysMenu> findSimpleByName(@Param(value="name") String name);

	List<SysMenu> findRoleMenus(@Param(value="roleId") Long roleId);
	
}

3.3.3、mapper

<?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.***.dao.SysMenuMapper">
  <resultMap id="BaseResultMap" type="com.***.model.SysMenu">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="parent_id" jdbcType="BIGINT" property="parentId" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="url" jdbcType="VARCHAR" property="url" />
    <result column="perms" jdbcType="VARCHAR" property="perms" />
    <result column="type" jdbcType="INTEGER" property="type" />
    <result column="icon" jdbcType="VARCHAR" property="icon" />
    <result column="order_num" jdbcType="INTEGER" property="orderNum" />
    <result column="create_by" jdbcType="BIGINT" property="createBy" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="last_update_by" jdbcType="BIGINT" property="lastUpdateBy" />
    <result column="last_update_time" jdbcType="TIMESTAMP" property="lastUpdateTime" />
    <result column="del_flag" jdbcType="TINYINT" property="delFlag" />
  </resultMap>
  <sql id="Base_Column_List">
    id, parent_id, name, url, perms, type, icon, order_num, create_by, create_time, 
    last_update_by, last_update_time, del_flag
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_menu
    where id = #{id,jdbcType=BIGINT}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    delete from sys_menu
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.***.model.SysMenu">
    insert into sys_menu (id, parent_id, name, 
      url, perms, type, icon, 
      order_num, create_by, create_time, 
      last_update_by, last_update_time, del_flag
      )
    values (#{id,jdbcType=BIGINT}, #{parentId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, 
      #{url,jdbcType=VARCHAR}, #{perms,jdbcType=VARCHAR}, #{type,jdbcType=INTEGER}, #{icon,jdbcType=VARCHAR}, 
      #{orderNum,jdbcType=INTEGER}, #{createBy,jdbcType=BIGINT}, #{createTime,jdbcType=TIMESTAMP}, 
      #{lastUpdateBy,jdbcType=BIGINT}, #{lastUpdateTime,jdbcType=TIMESTAMP}, #{delFlag,jdbcType=TINYINT}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.***.model.SysMenu">
    insert into sys_menu
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="parentId != null">
        parent_id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="url != null">
        url,
      </if>
      <if test="perms != null">
        perms,
      </if>
      <if test="type != null">
        type,
      </if>
      <if test="icon != null">
        icon,
      </if>
      <if test="orderNum != null">
        order_num,
      </if>
      <if test="createBy != null">
        create_by,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="lastUpdateBy != null">
        last_update_by,
      </if>
      <if test="lastUpdateTime != null">
        last_update_time,
      </if>
      <if test="delFlag != null">
        del_flag,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="parentId != null">
        #{parentId,jdbcType=BIGINT},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="url != null">
        #{url,jdbcType=VARCHAR},
      </if>
      <if test="perms != null">
        #{perms,jdbcType=VARCHAR},
      </if>
      <if test="type != null">
        #{type,jdbcType=INTEGER},
      </if>
      <if test="icon != null">
        #{icon,jdbcType=VARCHAR},
      </if>
      <if test="orderNum != null">
        #{orderNum,jdbcType=INTEGER},
      </if>
      <if test="createBy != null">
        #{createBy,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="lastUpdateBy != null">
        #{lastUpdateBy,jdbcType=BIGINT},
      </if>
      <if test="lastUpdateTime != null">
        #{lastUpdateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="delFlag != null">
        #{delFlag,jdbcType=TINYINT},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.***.model.SysMenu">
    update sys_menu
    <set>
      <if test="parentId != null">
        parent_id = #{parentId,jdbcType=BIGINT},
      </if>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="url != null">
        url = #{url,jdbcType=VARCHAR},
      </if>
      <if test="perms != null">
        perms = #{perms,jdbcType=VARCHAR},
      </if>
      <if test="type != null">
        type = #{type,jdbcType=INTEGER},
      </if>
      <if test="icon != null">
        icon = #{icon,jdbcType=VARCHAR},
      </if>
      <if test="orderNum != null">
        order_num = #{orderNum,jdbcType=INTEGER},
      </if>
      <if test="createBy != null">
        create_by = #{createBy,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="lastUpdateBy != null">
        last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
      </if>
      <if test="lastUpdateTime != null">
        last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="delFlag != null">
        del_flag = #{delFlag,jdbcType=TINYINT},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.***.model.SysMenu">
    update sys_menu
    set parent_id = #{parentId,jdbcType=BIGINT},
      name = #{name,jdbcType=VARCHAR},
      url = #{url,jdbcType=VARCHAR},
      perms = #{perms,jdbcType=VARCHAR},
      type = #{type,jdbcType=INTEGER},
      icon = #{icon,jdbcType=VARCHAR},
      order_num = #{orderNum,jdbcType=INTEGER},
      create_by = #{createBy,jdbcType=BIGINT},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
      last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
      del_flag = #{delFlag,jdbcType=TINYINT}
    where id = #{id,jdbcType=BIGINT}
  </update>
  <select id="findAll"  resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_menu
  </select>
  <select id="findPage"  resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_menu
  </select>
  <select id="findPageByName" parameterType="java.lang.String" resultMap="BaseResultMap">
  	<bind name="pattern" value="'%' + _parameter.name + '%'" />
    select 
    <include refid="Base_Column_List" />
    from sys_menu
    where name like #{pattern}
  </select>
  <select id="findByUserName" parameterType="java.lang.String" resultMap="BaseResultMap">
  	select m.* from sys_menu m, sys_user u, sys_user_role ur, sys_role_menu rm
  	where u.name = #{userName,jdbcType=BIGINT} and u.id = ur.user_id 
  	and ur.role_id = rm.role_id and rm.menu_id = m.id
  </select>
  <select id="findByName" parameterType="java.lang.String" resultMap="BaseResultMap">
  	select m.* from sys_menu m, sys_user u, sys_user_role ur, sys_role_menu rm
  	where m.name = #{name,jdbcType=VARCHAR} and u.id = ur.user_id 
  	and ur.role_id = rm.role_id and rm.menu_id = m.id
  </select>
  <select id="findSimpleByName" parameterType="java.lang.String" resultMap="BaseResultMap">
  	select m.* from sys_menu m
  	where m.name = #{name,jdbcType=VARCHAR}
  </select>
  <select id="findRoleMenus" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select m.* from sys_menu m, sys_role_menu rm
    where rm.role_id = #{roleId,jdbcType=BIGINT}
    and m.id = rm.menu_id
  </select>
</mapper>

3.3.4、service以及impl

public interface SysMenuService extends CurdService<SysMenu> {

	/**
	 * 查詢菜單樹,用戶ID和用戶名爲空則查詢全部
	 * @param menuType 獲取菜單類型,0:獲取所有菜單,包含按鈕,1:獲取所有菜單,不包含按鈕
	 * @param userId 
	 * @return
	 */
	List<SysMenu> findTree(String userName, int menuType,String name);

	/**
	 * 根據用戶名查找菜單列表
	 * @param userName
	 * @return
	 */
	List<SysMenu> findByUser(String userName, String name);
	
	List<SysMenu> findByName(String name);
}
@Service
public class SysMenuServiceImpl implements SysMenuService {

	@Autowired
	private SysMenuMapper sysMenuMapper;

	@Override
	public int save(SysMenu record) {
		if(record.getId() == null || record.getId() == 0) {
			return sysMenuMapper.insertSelective(record);
		}
		if(record.getParentId() == null) {
			record.setParentId(0L);
		}
		return sysMenuMapper.updateByPrimaryKeySelective(record);
	}

	@Override
	public int delete(SysMenu record) {
		return sysMenuMapper.deleteByPrimaryKey(record.getId());
	}

	@Override
	public int delete(List<SysMenu> records) {
		for(SysMenu record:records) {
			delete(record);
		}
		return 1;
	}

	@Override
	public SysMenu findById(Long id) {
		return sysMenuMapper.selectByPrimaryKey(id);
	}

	@Override
	public PageResult findPage(PageRequest pageRequest) {
		return MybatisPageHelper.findPage(pageRequest, sysMenuMapper);
	}
	
	@Override
	public List<SysMenu> findTree(String userName, int menuType,String name) {
		List<SysMenu> sysMenus = new ArrayList<>();
		List<SysMenu> menus = findByUser(userName,name);
		for (SysMenu menu : menus) {
			if (menu.getParentId() == null || menu.getParentId() == 0) {
				menu.setLevel(0);
				if(!exists(sysMenus, menu)) {
					sysMenus.add(menu);
				}
			}
		}
		sysMenus.sort((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()));
		findChildren(sysMenus, menus, menuType);
		return sysMenus;
	}

	@Override
	public List<SysMenu> findByUser(String userName, String name) {
		if(!StringUtils.isBlank(name)) {
			return sysMenuMapper.findByName(name);
		}
		if(userName == null || "".equals(userName) || SysConstants.ADMIN.equalsIgnoreCase(userName)) {
			return sysMenuMapper.findAll();
		}
		return sysMenuMapper.findByUserName(userName);
	}

	private void findChildren(List<SysMenu> SysMenus, List<SysMenu> menus, int menuType) {
		for (SysMenu SysMenu : SysMenus) {
			List<SysMenu> children = new ArrayList<>();
			for (SysMenu menu : menus) {
				if(menuType == 1 && menu.getType() == 2) {
					// 如果是獲取類型不需要按鈕,且菜單類型是按鈕的,直接過濾掉
					continue ;
				}
				if (SysMenu.getId() != null && SysMenu.getId().equals(menu.getParentId())) {
					menu.setParentName(SysMenu.getName());
					menu.setLevel(SysMenu.getLevel() + 1);
					if(!exists(children, menu)) {
						children.add(menu);
					}
				}
			}
			SysMenu.setChildren(children);
			children.sort((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()));
			findChildren(children, menus, menuType);
		}
	}

	private boolean exists(List<SysMenu> sysMenus, SysMenu sysMenu) {
		boolean exist = false;
		for(SysMenu menu:sysMenus) {
			if(menu.getId().equals(sysMenu.getId())) {
				exist = true;
			}
		}
		return exist;
	}

	@Override
	public List<SysMenu> findByName(String name) {
		return sysMenuMapper.findSimpleByName(name);
	}
	
}

 這裏查找樹形菜單時使用了遞歸的方法。

重點方法:findTree、findChildren

3.4、用戶角色

3.4.1、model

public class SysUserRole extends BaseModel {

    private Long userId;

    private Long roleId;

	public Long getUserId() {
		return userId;
	}

	public void setUserId(Long userId) {
		this.userId = userId;
	}

	public Long getRoleId() {
		return roleId;
	}

	public void setRoleId(Long roleId) {
		this.roleId = roleId;
	}

}

3.4.2、dao

public interface SysUserRoleMapper {
    int deleteByPrimaryKey(Long id);

    int insert(SysUserRole record);

    int insertSelective(SysUserRole record);

    SysUserRole selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(SysUserRole record);

    int updateByPrimaryKey(SysUserRole record);

	List<SysUserRole> findUserRoles(@Param(value="userId") Long userId);

	int deleteByUserId(@Param(value="userId") Long userId);
}

3.4.3、mapper

<?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.***.dao.SysUserRoleMapper">
  <resultMap id="BaseResultMap" type="com.***.model.SysUserRole">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="user_id" jdbcType="BIGINT" property="userId" />
    <result column="role_id" jdbcType="BIGINT" property="roleId" />
  </resultMap>
  <sql id="Base_Column_List">
    id, user_id, role_id
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_user_role
    where id = #{id,jdbcType=BIGINT}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    delete from sys_user_role
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.***.model.SysUserRole">
    insert into sys_user_role (id, user_id, role_id
      )
    values (#{id,jdbcType=BIGINT}, #{userId,jdbcType=BIGINT}, #{roleId,jdbcType=BIGINT}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.***.model.SysUserRole">
    insert into sys_user_role
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="userId != null">
        user_id,
      </if>
      <if test="roleId != null">
        role_id,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="userId != null">
        #{userId,jdbcType=BIGINT},
      </if>
      <if test="roleId != null">
        #{roleId,jdbcType=BIGINT},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.***.model.SysUserRole">
    update sys_user_role
    <set>
      <if test="userId != null">
        user_id = #{userId,jdbcType=BIGINT},
      </if>
      <if test="roleId != null">
        role_id = #{roleId,jdbcType=BIGINT},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.***.model.SysUserRole">
    update sys_user_role
    set user_id = #{userId,jdbcType=BIGINT},
      role_id = #{roleId,jdbcType=BIGINT}
    where id = #{id,jdbcType=BIGINT}
  </update>
  <select id="findUserRoles" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_user_role
    where user_id = #{userId,jdbcType=BIGINT}
  </select>
  <delete id="deleteByUserId" parameterType="java.lang.Long">
    delete from sys_user_role
    where user_id = #{userId,jdbcType=BIGINT}
  </delete>
</mapper>

3.4.4、service以及impl

詳見SysUserService和SysRoleService

3.5、角色菜單

3.5.1、model

public class SysRoleMenu extends BaseModel {

    private Long roleId;

    private Long menuId;

	public Long getRoleId() {
		return roleId;
	}

	public void setRoleId(Long roleId) {
		this.roleId = roleId;
	}

	public Long getMenuId() {
		return menuId;
	}

	public void setMenuId(Long menuId) {
		this.menuId = menuId;
	}

}

3.5.2、dao

public interface SysRoleMenuMapper {
    int deleteByPrimaryKey(Long id);

    int insert(SysRoleMenu record);

    int insertSelective(SysRoleMenu record);

    SysRoleMenu selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(SysRoleMenu record);

    int updateByPrimaryKey(SysRoleMenu record);

	List<SysRoleMenu> findRoleMenus(@Param(value="roleId") Long roleId);
	
	List<SysRoleMenu> findAll();

	int deleteByRoleId(@Param(value="roleId") Long roleId);
}

3.5.3、mapper

<?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.***.dao.SysRoleMenuMapper">
  <resultMap id="BaseResultMap" type="com.***.model.SysRoleMenu">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="role_id" jdbcType="BIGINT" property="roleId" />
    <result column="menu_id" jdbcType="BIGINT" property="menuId" />
    <result column="create_by" jdbcType="BIGINT" property="createBy" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="last_update_by" jdbcType="BIGINT" property="lastUpdateBy" />
    <result column="last_update_time" jdbcType="TIMESTAMP" property="lastUpdateTime" />
  </resultMap>
  <sql id="Base_Column_List">
    id, role_id, menu_id, create_by, create_time, last_update_by, last_update_time
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_role_menu
    where id = #{id,jdbcType=BIGINT}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    delete from sys_role_menu
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.***.model.SysRoleMenu">
    insert into sys_role_menu (id, role_id, menu_id, 
      create_by, create_time, last_update_by, 
      last_update_time)
    values (#{id,jdbcType=BIGINT}, #{roleId,jdbcType=BIGINT}, #{menuId,jdbcType=BIGINT}, 
      #{createBy,jdbcType=BIGINT}, #{createTime,jdbcType=TIMESTAMP}, #{lastUpdateBy,jdbcType=BIGINT}, 
      #{lastUpdateTime,jdbcType=TIMESTAMP})
  </insert>
  <insert id="insertSelective" parameterType="com.***.model.SysRoleMenu">
    insert into sys_role_menu
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="roleId != null">
        role_id,
      </if>
      <if test="menuId != null">
        menu_id,
      </if>
      <if test="createBy != null">
        create_by,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="lastUpdateBy != null">
        last_update_by,
      </if>
      <if test="lastUpdateTime != null">
        last_update_time,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="roleId != null">
        #{roleId,jdbcType=BIGINT},
      </if>
      <if test="menuId != null">
        #{menuId,jdbcType=BIGINT},
      </if>
      <if test="createBy != null">
        #{createBy,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="lastUpdateBy != null">
        #{lastUpdateBy,jdbcType=BIGINT},
      </if>
      <if test="lastUpdateTime != null">
        #{lastUpdateTime,jdbcType=TIMESTAMP},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.***.model.SysRoleMenu">
    update sys_role_menu
    <set>
      <if test="roleId != null">
        role_id = #{roleId,jdbcType=BIGINT},
      </if>
      <if test="menuId != null">
        menu_id = #{menuId,jdbcType=BIGINT},
      </if>
      <if test="createBy != null">
        create_by = #{createBy,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="lastUpdateBy != null">
        last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
      </if>
      <if test="lastUpdateTime != null">
        last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.***.model.SysRoleMenu">
    update sys_role_menu
    set role_id = #{roleId,jdbcType=BIGINT},
      menu_id = #{menuId,jdbcType=BIGINT},
      create_by = #{createBy,jdbcType=BIGINT},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      last_update_by = #{lastUpdateBy,jdbcType=BIGINT},
      last_update_time = #{lastUpdateTime,jdbcType=TIMESTAMP}
    where id = #{id,jdbcType=BIGINT}
  </update>
  <select id="findRoleMenus" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_role_menu
    where role_id = #{roleId,jdbcType=BIGINT}
  </select>
  <select id="findAll" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from sys_role_menu
  </select>
  <delete id="deleteByRoleId" parameterType="java.lang.Long">
    delete from sys_role_menu
    where role_id = #{roleId,jdbcType=BIGINT}
  </delete>
</mapper>

3.5.4、service以及impl

詳見SysUserService和SysRoleService

4、controller層調用及其他相關

根據用戶名查找角色:

//	@RequiresPermissions("sys:user:view")
	@GetMapping(value="/findByName")
	public HttpResult findByUserName(@RequestParam String name) {
		return HttpResult.ok(sysRoleService.findRoleByName(name));
	}

根據角色查找菜單:

	@RequiresPermissions("sys:role:view")
	@GetMapping(value="/findRoleMenus")
	public HttpResult findRoleMenus(@RequestParam Long roleId) {
		return HttpResult.ok(sysRoleService.findRoleMenus(roleId));
	}

(其實都是直接調用service方法,至於方法是幹啥的,稍微懂點英文就行了吧 /笑哭/笑哭/笑哭/笑哭)

還有就是,從上面代碼也能看到一個註解:@RequiresPermissions,這玩意就是權限,放在庫裏就是這樣:

實現方式是shiro+oauth2,首先寫個shiro配置:

@Configuration
public class ShiroConfig {
	
    @Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
		shiroFilter.setSecurityManager(securityManager);
		// 自定義 OAuth2Filter 過濾器,替代默認的過濾器
		Map<String, Filter> filters = new HashMap<>();
		filters.put("oauth2", new OAuth2Filter());
		shiroFilter.setFilters(filters);
		// 訪問路徑攔截配置,"anon"表示無需驗證,未登錄也可訪問
		Map<String, String> filterMap = new LinkedHashMap<>();
		// 首頁和登錄頁面
		filterMap.put("/", "anon");
		filterMap.put("/login", "anon"); 
        // 圖片
        filterMap.put("/images/**", "anon");
        // 其他所有路徑交給OAuth2Filter處理
		filterMap.put("/**", "oauth2");
		shiroFilter.setFilterChainDefinitionMap(filterMap);
		return shiroFilter;
	}

    @Bean
	public SecurityManager securityManager(){
	    DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
	    // 注入 Realm 實現類,實現自己的登錄邏輯
	    securityManager.setRealm(getShiroRealm());
	    return securityManager;
	}

	@Bean
    public Realm getShiroRealm(){
    	OAuth2Realm myShiroRealm = new OAuth2Realm();
        return myShiroRealm;
    }
	
    /**
     * Shiro生命週期處理器
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    
    /**
     * 開啓Shiro的註解(如@RequiresRoles,@RequiresPermissions),需藉助SpringAOP掃描使用Shiro註解的類,並在必要時進行安全邏輯驗證
     * 配置以下兩個bean(DefaultAdvisorAutoProxyCreator(可選)和AuthorizationAttributeSourceAdvisor)即可實現此功能
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
}

 然後是oauth2三個類:

public class OAuth2Filter extends AuthenticatingFilter {

    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
        // 獲取請求token
        String token = getRequestToken((HttpServletRequest) request);
        if(StringUtils.isBlank(token)){
            return null;
        }
        return new OAuth2Token(token);
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
    	return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    	HttpServletRequest httpRequest = (HttpServletRequest) request;
    	if("OPTIONS".equals(httpRequest.getMethod())) {
    		// 如果是跨域中複雜請求的預檢請求(OPTIONS類型),因爲預檢請求不帶token, 所以不需要驗證token
    		 return true;
    	}
        // 獲取請求token,如果token不存在,直接返回401
        String token = getRequestToken(httpRequest);
        if(StringUtils.isBlank(token)){
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setContentType("application/json; charset=utf-8");
            HttpResult result = HttpResult.error(HttpStatus.SC_UNAUTHORIZED, "invalid token");
            String json = JSONObject.toJSONString(result);
			httpResponse.getWriter().print(json);
            return false;
        }
        return executeLogin(request, response);
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setContentType("application/json; charset=utf-8");
        try {
            // 處理登錄失敗的異常
            Throwable throwable = e.getCause() == null ? e : e.getCause();
            HttpResult result = HttpResult.error(HttpStatus.SC_UNAUTHORIZED, throwable.getMessage());
            String json = JSONObject.toJSONString(result);
            httpResponse.getWriter().print(json);
        } catch (IOException e1) {
        }
        return false;
    }

    /**
     * 獲取請求的token
     */
    private String getRequestToken(HttpServletRequest httpRequest){
        // 從header中獲取token
        String token = httpRequest.getHeader("token");
        // 如果header中不存在token,則從參數中獲取token
        if(StringUtils.isBlank(token)){
            token = httpRequest.getParameter("token");
        }
        return token;
    }

}

 

@Component
public class OAuth2Realm extends AuthorizingRealm {

	@Autowired
	SysUserMapper sysUserMapper;
	@Autowired
	SysMenuMapper sysMenuMapper;
	@Autowired
	SysUserTokenMapper sysUserTokenMapper;
	
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof OAuth2Token;
    }

    /**
     * 授權(接口保護,驗證接口調用權限時調用)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SysUser user = (SysUser)principals.getPrimaryPrincipal();
        // 用戶權限列表,根據用戶擁有的權限標識與如 @permission標註的接口對比,決定是否可以調用接口
        Set<String> permsSet = findPermissions(user.getName());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permsSet);
        return info;
    }

    /**
     * 認證(登錄時調用)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String token = (String) authenticationToken.getPrincipal();
        // 根據accessToken,查詢用戶token信息
        SysUserToken sysUserToken = sysUserTokenMapper.findByToken(token);
        if(sysUserToken == null || sysUserToken.getExpireTime().getTime() < System.currentTimeMillis()){
        	// token已經失效
            throw new IncorrectCredentialsException("token失效,請重新登錄");
        }
        // 查詢用戶信息
        SysUser user = sysUserMapper.selectByPrimaryKey(sysUserToken.getUserId());
        // 賬號被鎖定
        if(user.getStatus() == 0){
            throw new LockedAccountException("賬號已被鎖定,請聯繫管理員");
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, token, getName());
        return info;
    }
    
    private Set<String> findPermissions(String userName) {	
		Set<String> perms = new HashSet<>();
		List<SysMenu> sysMenus = findByUser(userName);
		for(SysMenu sysMenu:sysMenus) {
			if(sysMenu.getPerms() != null && !"".equals(sysMenu.getPerms())) {
				perms.add(sysMenu.getPerms());
			}
		}
		return perms;
	}
    
    private List<SysMenu> findByUser(String userName) {
		if(userName == null || "".equals(userName) || SysConstants.ADMIN.equalsIgnoreCase(userName)) {
			return sysMenuMapper.findAll();
		}
		return sysMenuMapper.findByUserName(userName);
	}
}

 

public class OAuth2Token implements AuthenticationToken {
	private static final long serialVersionUID = 1L;
	
	private String token;

    public OAuth2Token(String token){
        this.token = token;
    }

    @Override
    public String getPrincipal() {
        return token;
    }

    @Override
    public Object getCredentials() {
        return token;
    }
}

 到這,基本上就算完工了,告辭!

附:

public class BaseModel {

	private Long id;
	
    private String createBy;

    private Date createTime;

    private String lastUpdateBy;

    private Date lastUpdateTime;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getCreateBy() {
		return createBy;
	}

	public void setCreateBy(String createBy) {
		this.createBy = createBy;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public String getLastUpdateBy() {
		return lastUpdateBy;
	}

	public void setLastUpdateBy(String lastUpdateBy) {
		this.lastUpdateBy = lastUpdateBy;
	}

	public Date getLastUpdateTime() {
		return lastUpdateTime;
	}

	public void setLastUpdateTime(Date lastUpdateTime) {
		this.lastUpdateTime = lastUpdateTime;
	}
    
}

 

public interface CurdService<T> {
	
	/**
	 * 保存操作
	 * @param record
	 * @return
	 */
	int save(T record);
	
	/**
	 * 刪除操作
	 * @param record
	 * @return
	 */
	int delete(T record);
	
	/**
	 * 批量刪除操作
	 * @param entities
	 */
	int delete(List<T> records);
	
	/**
	 * 根據ID查詢
	 * @param id
	 * @return
	 */
	T findById(Long id);
	
    /**
     * 分頁查詢
	 * 這裏統一封裝了分頁請求和結果,避免直接引入具體框架的分頁對象, 如MyBatis或JPA的分頁對象
	 * 從而避免因爲替換ORM框架而導致服務層、控制層的分頁接口也需要變動的情況,替換ORM框架也不會
	 * 影響服務層以上的分頁接口,起到了解耦的作用
	 * @param pageRequest 自定義,統一分頁查詢請求
	 * @return PageResult 自定義,統一分頁查詢結果
     */
	PageResult findPage(PageRequest pageRequest);
	
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章