𝑰’𝒎 𝒉𝒉𝒈, 𝑰 𝒂𝒎 𝒂 𝒈𝒓𝒂𝒅𝒖𝒂𝒕𝒆 𝒔𝒕𝒖𝒅𝒆𝒏𝒕 𝒇𝒓𝒐𝒎 𝑵𝒂𝒏𝒋𝒊𝒏𝒈, 𝑪𝒉𝒊𝒏𝒂.

  • 🏫 𝑺𝒉𝒄𝒐𝒐𝒍: 𝑯𝒐𝒉𝒂𝒊 𝑼𝒏𝒊𝒗𝒆𝒓𝒔𝒊𝒕𝒚
  • 🌱 𝑳𝒆𝒂𝒓𝒏𝒊𝒏𝒈: 𝑰’𝒎 𝒄𝒖𝒓𝒓𝒆𝒏𝒕𝒍𝒚 𝒍𝒆𝒂𝒓𝒏𝒊𝒏𝒈 𝒅𝒆𝒔𝒊𝒈𝒏 𝒑𝒂𝒕𝒕𝒆𝒓𝒏, 𝑳𝒆𝒆𝒕𝒄𝒐𝒅𝒆, 𝒅𝒊𝒔𝒕𝒓𝒊𝒃𝒖𝒕𝒆𝒅 𝒔𝒚𝒔𝒕𝒆𝒎, 𝒎𝒊𝒅𝒅𝒍𝒆𝒘𝒂𝒓𝒆 𝒂𝒏𝒅 𝒔𝒐 𝒐𝒏.
  • 💼 𝑷𝒓𝒐𝒇𝒆𝒔𝒔𝒊𝒐𝒏𝒂𝒍 𝒔𝒌𝒊𝒍𝒍𝒔:𝒎𝒚 𝒅𝒓𝒆𝒂𝒎

若依中的字典在java根据码值转为对应的汉字 若依数据字典_redis

1-1:查看接口

若依中的字典在java根据码值转为对应的汉字 若依数据字典_数据_02

1-2:/system/dict/data/type/sys_normal_disable和/system/dict/data/type/sys_user_sex

找接口:

这两个接口都是同一个,用idea 查接口的工具搜一下:

若依中的字典在java根据码值转为对应的汉字 若依数据字典_数据_03


数据字典:

这里涉及到一个数据字典的概念,数据字典用来干嘛,比如这里的两个请求分别对应了两个下拉框:

若依中的字典在java根据码值转为对应的汉字 若依数据字典_sql_04


为什么要查后台呢?因为这些如果前台写死了,那么我突然要加一个进去怎么加?就必须重新修改前端然后去再发一个版本才能加上去,如果说我动态访问后端,由后端到数据库里读,然后前端显示,这样就能解决这个问题了。令我不解的是,为什么若依有的是用来做数据字典,有的确没有加入到字典中去。

Redis中进行缓存:
数据字典访问核心代码:

@Override
public List<SysDictData> selectDictDataByType(String dictType)
{
    List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
    if (StringUtils.isNotEmpty(dictDatas))
    {
        return dictDatas;
    }
    dictDatas = dictDataMapper.selectDictDataByType(dictType);
    if (StringUtils.isNotEmpty(dictDatas))
    {
        DictUtils.setDictCache(dictType, dictDatas);
        return dictDatas;
    }
    return null;
}

很明显,数据字典是不经常修改的,所以redis是最好的归宿,这里就是常规的redis操作。

1-3:/system/user/list?pageNum=1&pageSize=10分页查找

1-3-1:分页PageHelper

我看PageHelper网上教程是通过配置文件实现的,比如这样:

若依中的字典在java根据码值转为对应的汉字 若依数据字典_java_05


但是我找半天也没在若依里面找到,于是仔细看了看,发现这些若依使用代码进行配置的。代码如下:

public class PageUtils extends PageHelper
{
    /**
     * 设置请求分页数据
     */
    public static void startPage()
    {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
        {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            Boolean reasonable = pageDomain.getReasonable();
            PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
        }
    }
}

大概就是从request请求中读几个参数,然后进行设置。

封装返回给前端的page对象:

protected TableDataInfo getDataTable(List<?> list)
{
    TableDataInfo rspData = new TableDataInfo();
    rspData.setCode(HttpStatus.SUCCESS);
    rspData.setRows(list);
    rspData.setMsg("查询成功");
    rspData.setTotal(new PageInfo(list).getTotal());
    return rspData;
}

分页怎么用的,基本上就是这些了。开始分页+查+封装分页返回对象。

1-3-2:dataScope 数据范围

相关包:

若依中的字典在java根据码值转为对应的汉字 若依数据字典_redis_06


一直好奇这个是用来干嘛的,直到遇见了才发现,这是一个数据范围的控制,也就是说控制一个用户,能看到的数据有哪些。

aspect中定义的权限等级:

/**
     * 全部数据权限
     */
    public static final String DATA_SCOPE_ALL = "1";

    /**
     * 自定数据权限
     */
    public static final String DATA_SCOPE_CUSTOM = "2";

    /**
     * 部门数据权限
     */
    public static final String DATA_SCOPE_DEPT = "3";

    /**
     * 部门及以下数据权限
     */
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";

    /**
     * 仅本人数据权限
     */
    public static final String DATA_SCOPE_SELF = "5";

具体实现:

先获取当前已经登陆的用户,查看这个user有哪些角色,对于这些角色,在数据库中能看到哪些部门,通过sql语句拼接,然后将sql语句存进user对象的参数field中,再到mapper中去拼接sql,mapper中的返回值是当前用户能看到的所有user。打开MySQL可以发现,datascope在role中设置的。

若依中的字典在java根据码值转为对应的汉字 若依数据字典_数据_07


注解里面的两个字段,deptAlias = “d”, userAlias = “u”,这两个是数据表的别名,可能是为了更灵活吧,因为放在了公共模块里面,当然越灵活越好。

/**
     * 数据范围过滤
     * 
     * @param joinPoint 切点
     * @param user 用户
     * @param deptAlias 部门别名
     * @param userAlias 用户别名
     */
    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
    {
        StringBuilder sqlString = new StringBuilder();

        for (SysRole role : user.getRoles())
        {
            String dataScope = role.getDataScope();
            if (DATA_SCOPE_ALL.equals(dataScope))
            {
                sqlString = new StringBuilder();
                break;
            }
            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
            {
                sqlString.append(StringUtils.format(
                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
                        role.getRoleId()));
            }
            else if (DATA_SCOPE_DEPT.equals(dataScope))
            {
                sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
            }
            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
            {
                sqlString.append(StringUtils.format(
                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
                        deptAlias, user.getDeptId(), user.getDeptId()));
            }
            else if (DATA_SCOPE_SELF.equals(dataScope))
            {
                if (StringUtils.isNotBlank(userAlias))
                {
                    sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
                }
                else
                {
                    // 数据权限为仅本人且没有userAlias别名不查询任何数据
                    sqlString.append(" OR 1=0 ");
                }
            }
        }

        if (StringUtils.isNotBlank(sqlString.toString()))
        {
            Object params = joinPoint.getArgs()[0];
            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
            {
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
            }
        }
    }

可以看一个例子:

@Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUserList(SysUser user)
    {
        return userMapper.selectUserList(user);
    }

除了上面的数据范围,如果你还想进行对当前用户已有的能看到的所有user,再次进行一个筛选,比如我看我对userId=2的这个用户,能不能看到他。我就在SysUser user对象里面设置一个id,mybatis里面会判空比如:

<if test="userId != null and userId != 0">
	AND u.user_id = #{userId}
</if>

最后的一个sql语句就是这样:

select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u left join sys_dept d on u.dept_id = d.dept_id where u.del_flag = '0' AND u.user_id = 5 AND (d.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = 2 ) );

AND (d.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = 2 )这个是AOP干的事情。

1-3-3:/system/dept/treeselect

/**
     * 获取部门下拉树列表
     */
    @GetMapping("/treeselect")
    public AjaxResult treeselect(SysDept dept)
    {
        List<SysDept> depts = deptService.selectDeptList(dept);
        return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
    }

就是从数据库中读所有部门,然后再构建一下树形结构,递归做一下,没有什么特别的。

1-3-4:/config/configKey/sys.user.initPassword

从数据库里面读初始密码,并且缓存起来,这个还挺简单的。